前言
这是stackoverflow上面的一个问题,原文地址What is the difference between @staticmethod and @classmethod in Python?,现将其翻译为中文,放在下面,仅供参考。
正文
问题:函数用@classmethod装饰和用@staticmethod装饰有什么区别?
回答:
回答一:unutbu:先举一个例子,看下面的代码,注意foo,class_foo,static_foo调用时的特征。1
2
3
4
5
6
7
8
9
10
11
12
13class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
def static_foo(x):
print "executing static_foo(%s)"%x
a=A()
下面是一个对象调用方法的常用方式,对象实例a作为第一个参数被隐式地传递过去。1
2a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
如果使用@classmethod,类对象实例的类型作为第一个参数被隐式地传递进来而非通过self的方式。1
2a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
也可以通过调用class_foo来使用类,事实上,如果你把一个东西定义成classmethod,那很有可能你试图通过类而非类的实例来调用它。A.foo(1)会引发TypeError异常,而使用A.class_foo(1)则可以正确运行。1
2A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
还有一种用途就是利用classmethod来创建可继承、可替代的构造器。
使用staticmethod,self(对象实例)或者cls(类型)都没有作为第一个参数进行传递。它看起来和普通的函数没什么区别,除非你能从一个类的实例或者类本身调用它。1
2
3
4
5a.static_foo(1)
# executing static_foo(1)
A.static_foo('hi')
# executing static_foo(hi)
staticmethod用来对类与类间有关联的函数进行分组。
foo只是一个函数,但是当你调用a.foo时你并不会得到这个函数,你会得到该函数的一个“局部适用”版本,并且将其与对象实例a绑定起来。foo需要两个参数,而a.foo只需要一个参数。
a和foo发生了绑定,下面这个例子简述了绑定的含义1
2print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
如果使用a.class_foo,则a不会和class_foo发生绑定,而是类A和class_foo发生了绑定1
2print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
使用staticmethod,虽然它是一个方法,但是a.static_foo只是返回一个函数而没有参数的绑定。static_foo需要一个参数,a.static_foot同样需要一个参数。1
2print(a.static_foo)
# <function static_foo at 0xb7d479cc>
类似,使用A.static_foo时也会有同样的效果1
2print(A.static_foo)
# <function static_foo at 0xb7d479cc>