109

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

class Dummy(object):

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

另一个是我从不使用的,主要是因为我不明白何时以及将其用于什么用途:

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

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

4

4 回答 4

83

您的猜测是正确的 - 您了解s classmethod的工作原理。

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

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()some_function在 的实际类型上调用 的版本self,而不是该调用碰巧出现的类(如果类被重命名,则不需要注意);和
  2. some_function需要实现某些协议但单独调用类对象很有用的情况下。

与 的区别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

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

于 2012-05-14T15:58:43.770 回答
0

Python中最常见的用途之一classmethod是工厂,它是构建对象的最有效方法之一。因为classmethods 和staticmethods 一样,不需要构造类实例。(但是如果我们使用staticmethod,我们将不得不在函数中硬编码实例类名)

这个博客很好地解释了它: https ://iscinumpy.gitlab.io/post/factory-classmethods-in-python/

于 2022-01-23T08:38:25.470 回答
-1

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

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

于 2020-02-27T18:11:28.453 回答
-4

如果你添加装饰器@classmethod,这意味着你要将该方法作为java或C++的静态方法。(我猜静态方法是一个通用术语;))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 并打印它。

并且在相同范围内使用相同名称的每个类或使用这些类构造的实例都将共享这些方法。只有一个 TestMethod.cls_var 也只有一个 TestMethod.class_method() , TestMethod.static_method()

和重要的问题。为什么需要这些方法。

classmethod 或 staticmethod 在您将该类作为工厂或只需要初始化一次类时很有用。就像打开文件一次,并使用 feed 方法逐行读取文件。

于 2012-05-14T15:59:47.243 回答