什么时候应该使用@classmethod和def方法(自我)?

mar*_*rue 72 python language-details method-dispatch class-method language-lawyer

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

class Dummy(object):

    def some_function(self,*args,**kwargs):
        do something here
        self is the class instance
Run Code Online (Sandbox Code Playgroud)

另一个是我不使用的,主要是因为我不明白何时使用它,以及为什么:

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        do something here
        cls refers to what?
Run Code Online (Sandbox Code Playgroud)

在Python文档中,classmethod装饰器用这句话解释:

类方法接收类作为隐式的第一个参数,就像实例方法接收实例一样.

所以我猜cls是指Dummy自己(class不是实例).我不完全理解为什么会这样,因为我总能做到这一点:

type(self).do_something_with_the_class
Run Code Online (Sandbox Code Playgroud)

这只是为了清楚起见,还是我错过了最重要的部分:如果没有它,那些怪异而迷人的东西是无法完成的?

Mar*_*cin 64

你的猜测是正确的 - 你了解它是如何 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()
Run Code Online (Sandbox Code Playgroud)

在实例上使用这些:在实例上调用classmethod至少有两个主要用途:

  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
Run Code Online (Sandbox Code Playgroud)

我发现它的主要用途是使现有函数(不希望接收a self)适应类(或对象)的方法.

  • @Voo实际上,`self.foo()`更可取,因为`self`可能是实现自己的`foo`的子类的实例. (5认同)
  • 不错的一个:我喜欢将答案分成如何 - 为什么。据我所知,@classmethod 允许在不需要实例的情况下访问该函数。这正是我要找的,谢谢。 (2认同)
  • 您应该为 `Bar` 使用不同的 lambda,因为 `1+1 == 2 == 1*2`,因此无法从显示的结果中判断出实际调用了 `Bar().static_method`。 (2认同)