Python中的 staticmethod 和 classmethod

众所周知,类是创建实例的模板,而实例是一个个具体的对象,各个实例拥有的数据相互独立、互不影响。

在类中定义的函数称为方法,主要有三种:实例方法、类方法、静态方法

class A:

    def instance_method(self, n):
        print('self', self)

    @classmethod
    def class_method(cls, n):
        print('cls', cls)

    @staticmethod
    def static_method():
        print('this is a static method')

上面类 A 定义的三个方法分别是实例方法、类方法、静态方法,下面我们来详细分析

实例方法

不带装饰器的实例方法在类定义中是最常见的:

定义中,传入的第一个参数必须是 self,表示实例本身,在其中可使用 self.attr 获取实例的属性。

a = A()
a.instance_method(2)
print(A.bar)
print(a.bar)

下面是程序运行结果:

self <__main__.A object at 0x0000028554C87E48>
grg
grg

当我们创建了实例 a 之后,调用 a.instance_method(2) 时,实例 a 会被自动传入函数作为 self 参数。

如果我们调用 A.instance_method(2) 时会发生什么呢?即,类能不能调用实例方法?

Traceback (most recent call last):
  File "I:\Program Code\Python\test2.py", line 32, in <module>
    A.instance_method(2)
TypeError: instance_method() missing 1 required positional argument: 'n'

可以看到,数字 2 被传入 self 参数了,所以才会提示缺少一个位置参数 n,所以,实例方法不能由类调用。

顺便提一句,属性也分实例属性和类属性,上例直接定义的是类属性,类和类实例都可以访问。类中定义的方法也可以无限制访问这个类属性。

通过 __init__(self,attr) 定义的是实例属性,只有实例能访问,类不能访问。类中定义的属性只有传进了 self 参数的方法(通常就是实例方法)可访问。

classmethod

无需实例化,但与实例方法第一个参数必须是 self 类似,类方法第一个参数表示类自身的 cls 参数,可以来调用类的属性、类的方法、类的实例化对象等

a.class_method(2)
A.class_method(2)

观察上面代码的运行结果:

cls <class '__main__.A'>
cls <class '__main__.A'>

可知,类方法既可以由类调用,也可以由实例调用。

再来看一个例子:

class Book(object):
    def __init__(self, title):
        self.title = title

    @classmethod
    def create(cls, title):
        book = cls(title)
        return book


book1 = Book('A song of Ice and Fire')
book2 = Book.create('The Marvel')
print(book1.title)
print(book2.title)

运行结果如下:

A song of Ice and Fire
The Marvel

上面,类方法创建了一个类实例。

staticmethod

无需 self 参数,无需 cls 参数,直接声明一个静态方法,可无需实例化,直接由类调用,也可实例化后调用。

带 staticmethod 装饰器定义的就是静态方法,与普通函数没有区别,可以不加参数,可以加任意参数,不必传入 self ,既可以由实例调用,也可以由类调用。

A.static_method()
a.static_method()

运行结果如下:

this is a static method
this is a static method

总结

实例方法只能由实例调用,类方法和静态方法可以由实例或类调用。

上一篇:python @staticmethod 注解,静态方法,可以省略类里那个self参数


下一篇:【Python面向对象】(5) @staticmethod和@classmethod