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

在集成一个我以前没有用过的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装饰classmethod这句话来解释:

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

所以我想cls是指Dummy本身( class ,而不是实例)。 我不完全明白为什么会这样,因为我总是可以这样做:

 type(self).do_something_with_the_class 

这只是为了清楚起见,还是我错过了最重要的部分:没有它的事情是不可能做到的令人着迷和迷人的事情?

你的猜测是正确的 – 你了解classmethod的工作方式。

为什么这些方法既可以在实例上也可以在类上调用(在这两种情况下,类对象都将作为第一个parameter passing):

 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() 

关于这些实例的使用:对实例调用一个类方法至less有两个主要用途:

  1. self.some_function()将调用some_function的实际types的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 )调整为类(或对象)上的方法。

如果你添加装饰@classmethod,那就意味着你要把这个方法作为java或C ++的静态方法。 (静态方法是我猜的一般术语 ;) )Python也有@staticmethod。 而classmethod和staticmethod的不同之处在于你是否可以使用参数或类名本身来访问类或静态variables。

 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方法逐行读取文件。