@classmethod和python中的方法之间的区别

本问题已经有最佳答案,请猛点这里访问。

@classmethod和python中的"经典"方法有什么区别,

什么时候应该使用@classmethod,什么时候应该使用python中的"经典"方法。classmethod必须是一个引用该类的方法吗(我的意思是它只是一个处理类的方法)?

我知道@staticmethod和经典方法的区别谢谢


如果你在一个类中定义了一个方法,它会以一种特殊的方式处理:访问它将它包装在一个特殊的对象中,这个对象修改了调用参数,以便包含self,一个对被引用对象的引用:

1
2
3
4
5
6
class A(object):
    def f(self):
        pass

a = A()
a.f()

这个对a.f的调用实际上要求f(通过描述符协议)对象真正返回。然后不带参数地调用该对象,并将调用转向实数f,在前面添加a

因此,a.f()真正做的是用(a)作为参数调用原始的f函数。

为了防止这种情况,我们可以对函数进行包装

使用@staticmethod装饰器,使用@classmethod装饰器,和另一个类似的人一起工作,自己做装饰。

@staticmethod将其转换为一个对象,当被请求时,该对象将改变传递参数的行为,使其符合调用原始f的意图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A(object):
    def method(self):
        pass
    @staticmethod
    def stmethod():
        pass
    @classmethod
    def clmethod(cls):
        pass

a = A()
a.method() # the"function inside" gets told about a
A.method() # doesn't work because there is no reference to the needed object
a.clmethod() # the"function inside" gets told about a's class, A
A.clmethod() # works as well, because we only need the classgets told about a's class, A
a.stmethod() # the"function inside" gets told nothing about anything
A.stmethod() # works as well

因此@classmethod@staticmethod有一个共同点,即它们"不关心"与它们一起调用的具体对象;区别在于@staticmethod根本不想知道关于它的任何信息,而@classmethod想知道它的类。

因此,后者获取所使用对象是其实例的类对象。在本例中,只需用cls替换self

什么时候用?

嗯,这很容易处理:

如果您可以访问self,那么显然需要一个实例方法。如果您不访问self,但想了解它的类,请使用@classmethod。例如,工厂方法可能就是这种情况。datetime.datetime.now()就是这样一个例子:您可以通过它的类或实例调用它,但是它创建了一个具有完全不同数据的新实例。我甚至曾经使用它们来自动生成给定类的子类。如果既不需要self也不需要cls,则使用@staticmethod。这也可以用于工厂方法,如果它们不需要关心子类化的话。


假设您有一个类Car,它表示系统中的Car实体。

classmethod是一个用于类Car的方法,而不是用于任何Car的实例。因此,用@classmethod修饰的函数的第一个参数(通常称为cls)是类本身。例子:

1
2
3
4
5
6
7
class Car(object):    
    colour = 'red'

    @classmethod
    def blue_cars(cls):
        # cls is the Car class
        # return all blue cars by looping over cls instances

函数作用于类的特定实例;第一个参数通常称为self是实例本身:

1
2
def get_colour(self):
    return self.colour

总结:

使用classmethod实现对整个类(而不是特定类实例)有效的方法:

1
Car.blue_cars()

使用实例方法实现对特定实例有效的方法:

1
2
my_car = Car(colour='red')
my_car.get_colour() # should return 'red'


@classmethod以类作为第一个参数,而function以类的实例作为参数

1
2
3
4
5
6
7
8
9
10
11
12
>>> class Test(object):
...     def func(self):
...         print self
...     @classmethod
...     def meth(self):
...         print self

>>> t = Test()
>>> t.func()
<__main__.Test object at 0x00000000027238D0>
>>> t.meth()
<class '__main__.Test'>

我故意在meth中使用了self参数,所以它在语法上非常接近func。但是通常你最好使用cls作为参数:

1
2
3
...     @classmethod
...     def meth(cls):
...         print cls