我应该何时使用@classmethod以及何时使用def方法(自己)?

问题描述 投票:79回答:3

虽然集成了我以前从未使用过的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

这仅仅是为了清楚起见,还是我想念最重要的部分:没有它就无法完成的怪异而令人着迷的事情?

python language-lawyer class-method method-dispatch language-details
3个回答
65
投票

您的猜测是正确的-您了解如何 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

我发现它的主要用途是将现有功能(不会收到self)改成类(或对象)上的方法。


0
投票

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


-2
投票

如果添加装饰器@classmethod,则意味着您将使该方法成为Java或C ++的静态方法。 (静态方法是一般术语

© www.soinside.com 2019 - 2024. All rights reserved.