#@staticmethod(静态方法)和@classmethod(类方法)有什么区别?
##问题:
用@staticmethod装饰的函数和用 @classmethod装饰的函数有什么区别?
##答案:
也许一些代码示例会有所帮助。注意foo
、 class_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
。事实上,如果你把某个东西定义为classmethod,可能是因为你打算从类而不是从类的实例中调用它。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)
Staticmethods用来对函数进行分组,这些函数和某个类有着逻辑关联。
foo
只是一个函数,但是当你调用a.foo
时,你得到的不只是函数本身,你还会得到该函数的一个“局部应用”的版本,并且对象实例被绑定为该函数的第一个参数。foo
有2个参数,而a.foo
只有1个参数。
下面这个术语“绑定”的意思是说:a
被绑定到foo
。
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
在a.class_foo
中,被绑定到class_foo
的不是a
,而是A
这个类。
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
尽管这里的staticmethod是一个方法,a.static_foo也只是返回函数,并且这个函数没有绑定的参数。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>
【编者注:另外对静态方法和类方法的比较,可以参考:《零基础学Python(第二版)之类(5)部分》】