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

时间:2012-05-14 15:54:17

标签: python language-lawyer class-method method-dispatch language-details

在集成我之前没有使用的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

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

3 个答案:

答案 0 :(得分:59)

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

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

  1. self.some_function()会在some_function的实际类型上调用self的版本,而不是该调用恰好出现的类(如果该类调用则不需要注意)被重命名);和
  2. 如果some_function是实现某些协议所必需的,但仅对类对象进行调用很有用。
  3. 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)适应类(或对象)的方法。

答案 1 :(得分:0)

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

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

答案 2 :(得分:-2)

如果你添加装饰器@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方法逐行读取文件。

相关问题