When should I use @classmethod and when def method(self)?

在集成一个我以前从未使用过的 Django 应用程序时,我发现了两种在类中定义函数的不同方法。作者似乎既独特又有意地使用了它们。第一个是我自己经常使用的:

class Dummy(object):


def some_function(self, *args, **kwargs):
# do something here
# self is the class instance

The other one is the one I never use, mostly because I do not understand when and what to use it for:

class Dummy(object):


@classmethod
def some_function(cls, *args, **kwargs):
# do something here
# cls refers to what?

Python 文档中的 classmethod装饰器说:

类方法接收该类作为隐式的第一个参数 类似于实例方法接收实例。

所以我猜 cls指的是 Dummy本身(class,而不是实例)。我不太明白为什么会有这种情况,因为我总是可以这样做:

type(self).do_something_with_the_class

这只是为了清晰起见,还是我错过了最重要的部分: 没有它就无法完成的幽灵般迷人的事情?

49468 次浏览

你的猜测是正确的-你了解 怎么做 classmethod的工作。

原因是这些方法都可以在类的实例 OR 上调用(在这两种情况下,类对象都将作为第一个参数传递) :

class Dummy(object):


@classmethod
def some_function(cls,*args,**kwargs):
print cls


#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()

关于在实例 上使用这些函数: 调用实例上的类方法至少有两个主要用途:

  1. self.some_function()将对 self的实际类型调用 some_function的版本,而不是调用恰好出现在其中的类(如果该类被重命名,则不需要注意) ;
  2. In cases where some_function is necessary to implement some protocol, but is useful to call on the class object alone.

staticmethod 的区别: 定义不访问实例数据的方法还有另一种方法,称为 staticmethod。这将创建一个根本不接收隐式第一个参数的方法; 因此它将不会被传递关于调用它的实例或类的任何信息。

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)


In [7]: Foo.some_static(1)
Out[7]: 2


In [8]: Foo().some_static(1)
Out[8]: 2


In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)


In [10]: Bar.some_static(1)
Out[10]: 2


In [11]: Bar().some_static(1)
Out[11]: 2

我发现它的主要用途是将现有函数(它不期望接收 self)改编为类(或对象)上的方法。

如果你添加了 decorator@classmethod,这意味着你要把这个方法作为 java 或 C + + 的静态方法。(static 方法是 通用术语,我猜是 ;)) Python 也有@staticmethod。 classmethod 和 staticmethod 的区别在于您是否可以 使用参数或类名本身访问类或静态变量。

class TestMethod(object):
cls_var = 1
@classmethod
def class_method(cls):
cls.cls_var += 1
print cls.cls_var


@staticmethod
def static_method():
TestMethod.cls_var += 1
print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()


#construct instances
testMethodInst1 = TestMethod()
testMethodInst2 = TestMethod()


#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()

所有这些类都将 cls.cls _ var 增加1并打印出来。

And every classes using same name on same scope or instances constructed with these class is going to share those methods. There's only one TestMethod.cls_var and also there's only one TestMethod.class_method() , TestMethod.static_method()

还有一个重要的问题,为什么需要这些方法。

将类作为工厂时,classmethod 或 staticmethod 非常有用 或者只需初始化类一次。像打开文件一次,并使用提要方法逐行读取文件。

基本上,当您意识到方法的定义不会被更改或重写时,应该使用@classmethod。

另外: 理论上,类方法比对象方法更快,因为不需要被实例化,并且需要更少的内存。

One of the most common uses of classmethod in Python is factories, which are one of the most efficient methods to build an object. Because classmethods, like staticmethods, do not need the construction of a class instance. (But then if we use staticmethod, we would have to hardcode the instance class name in the function)

This blog does a great job of explaining it: Https://iscinumpy.gitlab.io/post/factory-classmethods-in-python/