Anders Wang


我所认识的每个人都是榜样,都有值得我去尊敬和学习的地方。


@classmethod与@staticmethod区别

在Python中有3种方式定义类方法分别是常规方式、@classmethod修饰方式、@staticmethod修饰方式。

接下来分别对3种不同方式的定义举例说明。

普通方法: 其实就是需要操作一些实例独有的属性,是实例而不是类。第一个参数一般是隐式地将实例传递给self参数。

class People():  
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def greeting(self):
        return f'Hello, {self.name}'

p = People('Anders', 'Male')  
p.greeting()

# 输出内容:
# 'Hello, Anders'

@staticmethod: 静态方法其实就是一个普通的函数(静态方法无法调用任何非静态成员,所以也不需要self参数),可以使用类名直接调用,很多人不太明白的是为什么不直接把静态方法放在类外调用呢,毕竟效果一样,但是从代码逻辑从属来说,静态方法是一种组织或风格特征。如果这个方法实现的功能与类比较相关的话,放到了类里面更合适,这代表是某个类专用的工具函数。

class People():  
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    @staticmethod
    def greeting(name, gender):
        return f'Hello, {name}!'

print(People.greeting('Anders', 'Male'))

# 输出内容:
# Hello, Anders!

静态方法调用另一个静态方法直接用「类名.静态方法()」调用即可。如果想在静态方法中调用类中的其它非静态方法,或者非静态属性必须要通过生成实例对象的方式去访问。

class Web(object):  
    def __init__(self):
        self.desc = "实例属性,不共享"

    def norm_method(self):
        """普通方法"""
        print('普通方法被调用!')

    # 另外一个静态方法
    @staticmethod
    def foo_staticmethod_other():
        print('另外一个静态方法被调用!')

    @staticmethod
    def foo_staticmethod():
        # 调用非静态方法和属性
        instance = Web()
        instance.norm_method()
        print(instance.desc)

        # 调用另一个静态方法
        print(Web.foo_staticmethod_other())

@classmethod: 类方法可以通过类或者实例对象调用。一般情况下是作用于类相关的操作。第一个参数不是类的实例对象,而必须是类对象,在Python中这个参数常被写作cls,因为全称class是保留字。而被@classmethod修饰的函数内可调用类属性,但不能调用实例属性。

注意:对类作出的任何改变会对它的所有实例对象产生影响。

我们看到下面创建了3次实例对象,当最后去访问类方法person时,count值累积为数值3,并没有还原。

class People():  
    count = 0

    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        People.count += 1

    @classmethod
    def person(cls):
        return cls.count

p1 = People('Anders', 'Male')  
p2 = People('Mary', 'Female')  
p3 = People('James', 'Male')

print(f'People has {People.person()} little person objects.')

# 输出内容:
# People has 3 little person objects.

那么类方法一般用在什么场景呢,举个如下例子,如果用户输入的时间日期格式和我们预期的纯数字不一致,比如'2019-03-03',那可以先使用get_date类方法对日期字符串进行处理,然后在使用时date = cls(year, month, day)做构造函数初始化并创建了一个date实例,最后我们把它return返回出来,然后赋值给result变量后就可以直接调用类实例方法了。

class Time_Data:  
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def get_date(cls, data_as_string):
        year, month, day = map(int, data_as_string.split('-'))
        date = cls(year, month, day)
        return date

    def out_date(self):
        print(f'The date is: {self.year}/{self.month}/{self.day}')


result = Time_Data.get_date('2019-03-03')  
result.out_date()

# 输出内容:
# The date is: 2019/3/3

总结起来就是,class method可以用来为一个类创建一些预处理的实例。

最近的文章

关于Python鸭子类型

Python对实现多态性的要求很宽松,这就代表我们可以对不同对象调用同名的操作,甚至不用关注和谐对象的类型是什么,我们称这样的方式叫做鸭子类型。说的再通俗一点,就是如果某个对象的形状像鸭子,走的像鸭子…

Python, 技术博文详细阅读
更早的文章

Python常用高阶函数

高阶函数是在Python中一个非常有用的功能函数,所谓高阶函数就是一个函数可以用来接收另一个函数作为参数,这样的函数叫做高阶函数。 为了便于理解,我们从实际例子来看看函数当做参数被传递到另个函数是什么…

Python, 技术博文详细阅读
comments powered by Disqus