用@staticmethod
修饰的函数有什么区别?一个用 @classmethod
装饰?
最佳答案
也许一些示例代码会有所帮助:注意 foo
、class_foo
和 static_foo
的调用签名的区别:
class A(object):
def foo(self, x):
print(f"executing foo({self}, {x})")
@classmethod
def class_foo(cls, x):
print(f"executing class_foo({cls}, {x})")
@staticmethod
def static_foo(x):
print(f"executing static_foo({x})")
a = A()
以下是对象实例调用方法的常用方式。对象实例 a
作为第一个参数隐式传递。
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)
使用 classmethods,对象实例的类作为第一个参数隐式传递,而不是 self
。
a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
您也可以使用类调用 class_foo
。事实上,如果你定义一些东西是
一个类方法,这可能是因为您打算从类而不是类实例中调用它。 A.foo(1)
会引发 TypeError,但 A.class_foo(1)
工作正常:
A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)
人们发现类方法的一个用途是创建 inheritable alternative constructors .
使用静态方法,self
(对象实例)和cls
(类)都不会作为第一个参数隐式传递。它们的行为类似于普通函数,只是您可以从实例或类中调用它们:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
静态方法用于对与类有某种逻辑联系的函数进行分组。
foo
只是一个函数,但是当您调用 a.foo
时,您不仅会得到该函数,
您将获得函数的“部分应用”版本,其中对象实例 a
绑定(bind)为函数的第一个参数。 foo
需要 2 个参数,而 a.foo
只需要 1 个参数。
a
绑定(bind)到 foo
。这就是下文“绑定(bind)”一词的含义:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
使用 a.class_foo
,a
不绑定(bind)到 class_foo
,而是类 A
绑定(bind)到class_foo
.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
这里,使用静态方法,即使它是一个方法,a.static_foo
只是返回
一个很好的 'ole 函数,没有绑定(bind)参数。 static_foo
需要 1 个参数,并且
a.static_foo
也需要 1 个参数。
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
当然,当您使用类 A
调用 static_foo
时,也会发生同样的事情。
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
https://stackoverflow.com/questions/136097/