用@staticmethod
修饰的函数和用@staticmethod
修饰的函数有@staticmethod
@classmethod
?
也许一些示例代码会有所帮助:注意foo
, class_foo
和static_foo
的调用签名的static_foo
:
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%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)
人们发现类方法的一个用途是创建可继承的替代构造函数 。
对于 staticmethods , self
(对象实例)和cls
(类)都不会作为第一个参数隐式传递。它们的行为类似于普通函数,除了您可以从实例或类中调用它们:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
Staticmethod 用于将与类有逻辑连接的函数分组到类中。
foo
仅仅是一个函数,但是当你调用a.foo
你不只是得到的功能,你会得到一个 “部分应用” 功能与对象实例的版本a
绑定作为第一个参数的函数。 foo
需要 2 个参数,而a.foo
只需要 1 个参数。
a
是foo
。这就是下面的 “绑定” 一词的含义:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
使用a.class_foo
, a
不绑定到class_foo
,而是将类A
绑定到class_foo
。
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
在这里,使用a.static_foo
方法,即使它是一个方法, a.static_foo
只返回一个没有参数绑定的良好'ole 函数。 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>
staticmethod是一种对调用它的类或实例一无所知的方法。它只是获取传递的参数,没有隐含的第一个参数。它在 Python 中基本没用 - 您可以使用模块函数而不是静态方法。
甲类方法 ,在另一方面,是获取传递的类,它被称为上,或该类的实例,它被称为上的,作为第一个参数的方法。当您希望该方法成为该类的工厂时,这很有用:因为它获取了作为第一个参数调用的实际类,所以即使涉及子类,也可以始终实例化正确的类。例如,观察dict.fromkeys()
在子类上调用时如何返回子类的实例:
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
基本上@classmethod
创建了一个方法,其第一个参数是从中调用的类(而不是类实例), @staticmethod
没有任何隐式参数。