Python 中@classmethod和@staticmethod的区别

前言

这是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
13
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作为第一个参数被隐式地传递过去。

1
2
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

如果使用@classmethod,类对象实例的类型作为第一个参数被隐式地传递进来而非通过self的方式。

1
2
a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

也可以通过调用class_foo来使用类,事实上,如果你把一个东西定义成classmethod,那很有可能你试图通过类而非类的实例来调用它。A.foo(1)会引发TypeError异常,而使用A.class_foo(1)则可以正确运行。

1
2
A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

还有一种用途就是利用classmethod来创建可继承、可替代的构造器

使用staticmethod,self(对象实例)或者cls(类型)都没有作为第一个参数进行传递。它看起来和普通的函数没什么区别,除非你能从一个类的实例或者类本身调用它。

1
2
3
4
5
a.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
2
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

如果使用a.class_foo,则a不会和class_foo发生绑定,而是类A和class_foo发生了绑定

1
2
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

使用staticmethod,虽然它是一个方法,但是a.static_foo只是返回一个函数而没有参数的绑定。static_foo需要一个参数,a.static_foot同样需要一个参数。

1
2
print(a.static_foo)
# <function static_foo at 0xb7d479cc>

类似,使用A.static_foo时也会有同样的效果

1
2
print(A.static_foo)
# <function static_foo at 0xb7d479cc>

文章目录
  1. 1. 前言
  2. 2. 正文
,