@classmethod和python中的"经典"方法有什么区别,
什么时候应该使用@classmethod,什么时候应该使用python中的"经典"方法。classmethod必须是一个引用该类的方法吗(我的意思是它只是一个处理类的方法)?
我知道@staticmethod和经典方法的区别谢谢
- 不,事实上我知道静态方法和方法之间的区别,我想知道什么时候使用@classmethod,什么时候在我的类中使用函数,以及这些方法之间的区别
- 然后讨论方法和@classmethod。
- 还请参阅python工厂函数最佳实践
- 它解释了什么是类方法,而不是类方法和方法之间的区别,以及什么时候应该使用@classmethod(使用cls)而不是方法(使用self参数)
如果你在一个类中定义了一个方法,它会以一种特殊的方式处理:访问它将它包装在一个特殊的对象中,这个对象修改了调用参数,以便包含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。这也可以用于工厂方法,如果它们不需要关心子类化的话。
- @classmethod接受第一个参数类。
- @MartijnPieters你是对的,我搞混了。
- 但是现在你的答案只谈论staticmethod,而不是classmethod……
- 这就是OP最初的意思;我现在添加了一个关于@classmethod的简短部分。
- 关于@staticmethod的答案不是@classmethod,而是错误的,因为@staticmethod的要点是,您可以调用A.f()而不必创建first的实例。
- +1实际上你已经回答了OP问题-他的意思是@staticmethod而不是@classmethod:)
- OP在注释中解释说,它们在问题中确实是指@classmethod。
- @SteveBarnes可以通过实例(a.f())和类(A.f())调用它。都是可能的。
- 但是@glglgl使@staicmethod独一无二的是,您可以在不使用实例的情况下调用它。这就是使用decorator的唯一真正原因。
假设您有一个类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 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 |
- 最好不要把它命名为self,而是cls。
- 谢谢,我知道,我使用self只是为了避免混淆,并且方法和函数声明尽可能紧密地放在一起