@classmethod
和python中的'经典'方法有什么区别,
我应该何时使用@classmethod
,何时应该在python中使用'经典'方法。
classmethod必须是一个被引用给类的方法(我的意思是它只是一个处理类的方法)?
我知道@staticmethod和经典方法之间有什么区别 THX
答案 0 :(得分:5)
如果在类中定义一个方法,它将以一种特殊的方式处理:对它的访问将其包装在一个特殊的对象中,该对象修改调用参数以包含self
,这是对引用对象的引用:
class A(object):
def f(self):
pass
a = A()
a.f()
此a.f
的来电实际上会f
(通过descriptor protocol)要求对象真正返回。然后在不带参数的情况下调用此对象,并将调用转移到真实f
,并在前面添加a
。
那么a.f()
真正做的是调用原始的f
函数并将(a)
作为参数。
为了防止这种情况,我们可以包装函数
@staticmethod
装饰器,@classmethod
装饰器, @staticmethod
将它变成一个对象,当被问到时,它会改变参数传递行为,使其与调用原始f
的意图相符:
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
想知道它的类。
因此后者获取类对象所使用的对象是其实例。在这种情况下,只需将self
替换为cls
。
现在,何时使用什么?
嗯,这很容易处理:
self
,则显然需要实例方法。self
,但想要了解其类,请使用@classmethod
。例如,这可以是工厂方法的情况。 datetime.datetime.now()
就是这样一个例子:您可以通过其类或实例调用它,但它会创建一个具有完全不同数据的新实例。我甚至使用它们一次来自动生成给定类的子类。self
也不需要cls
,则可以使用@staticmethod
。如果他们不需要关心子类化,这也可以用于工厂方法。答案 1 :(得分:4)
假设您有一个类Car
,它代表系统中的Car
实体。
classmethod
是一种适用于Car
类的方法,不适用于任何Car
个实例之一。因此,用@classmethod
修饰的函数的第一个参数(通常称为cls
)就是类本身。例如:
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
的第一个参数是实例本身:
def get_colour(self):
return self.colour
总结一下:
使用classmethod
来实现适用于整个类的方法(而不是特定的类实例):
Car.blue_cars()
使用实例方法实现适用于特定实例的方法:
my_car = Car(colour='red')
my_car.get_colour() # should return 'red'
答案 2 :(得分:2)
@classmethod
将类作为第一个参数,而function接受类
>>> 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'>
我故意在self
中使用meth
参数,因此它与func
的语法非常接近。但通常你最好使用cls
作为参数:
... @classmethod
... def meth(cls):
... print cls