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

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

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

1
2
3
4
5
class Dummy(object):

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

另一个是我不使用的,主要是因为我不知道什么时候使用它,以及为什么:

1
2
3
4
5
6
class Dummy(object):

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

在python文档中,classmethod修饰器用以下句子解释:

A class method receives the class as implicit first argument, just
like an instance method receives the instance.

所以我猜cls是指Dummy本身(class不是实例)。我不完全理解为什么会存在这种情况,因为我可以一直这样做:

1
type(self).do_something_with_the_class

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


你的猜测是正确的——你知道classmethod的工作原理。

为什么可以在实例或类上同时调用这些方法(在这两种情况下,类对象都将作为第一个参数传递):

1
2
3
4
5
6
7
8
9
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至少有两种主要用途:

  • self.some_function()将对实际类型的self调用some_function的版本,而不是调用发生在其中的类(如果该类被重命名,则不需要注意);以及
  • 在一些情况下,some_function是实现某些协议所必需的,但对于单独调用类对象很有用。
  • staticmethod的区别在于:有另一种方法定义不访问实例数据的方法,称为staticmethod。它创建了一个根本不接收隐式第一个参数的方法;因此,它不会被传递有关调用它的实例或类的任何信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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作为类(或对象)上的方法)进行调整。


    如果你添加了装饰器@ Cube方法,那就意味着你要把这个方法作为Java或C++的静态方法。(我想静态方法是一个通用术语;)python也有@staticmethod。ClassMethod和StaticMethod的区别在于使用参数或类名本身访问类或静态变量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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()。

    以及重要问题。为什么需要这些方法。

    类方法或静态方法在将该类作为工厂时是有用的。或者当你必须只初始化你的班级一次。如打开文件一次,并使用FIX方法逐行读取文件。