Python中@staticmethod和@classmethod有什么区别?
用@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)
在类方法中 ,对象实例的类作为第一个参数隐式传递,而不是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)
人们发现一种用于类方法的方法是创建可继承的替代构造函数。
使用静态方法 , self
(对象实例)和cls
(类)都不会作为第一个参数隐式传递。 除了可以从实例或类中调用它们之外,它们的行为与普通函数类似:
a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
静态方法用于对与类具有某种逻辑连接的函数进行分组。
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
只是返回一个没有绑定参数的好的'ole函数。 static_foo
需要1个参数,而a.static_foo
需要1个参数。
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
当然,当你用class A
调用static_foo
,会发生同样的事情。
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
静态方法是一种对它所调用的类或实例一无所知的方法。 它只是获得通过的参数,没有隐含的第一个参数。 在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
没有任何隐式参数。
上一篇: What is the difference between @staticmethod and @classmethod in Python?