问题描述
我目前正在学习Python。在OOP中,@classmethod
装饰器的用途是什么?通过@classmethod
访问类变量并仅通过常规方法访问它有什么区别?就像我可以这样做一样:
class A():
_variable = A
def getvariable(self):
return self._variable
或
class A():
_variable = A
@classmethod
def getvariable(cls):
return cls._variable
两种方法有什么区别?为什么在什么时候使用classmethod以及什么时候不需要使用classmethod?如果我不这样做会怎样?
解决方法
使用类和实例变量/方法时,您关心的是可见性!
该类的所有实例共享一个类变量/方法,而该实例变量/方法仅可用于您当前拥有的实例!
通常来说,实例变量用于每个实例唯一的数据,而类变量用于该类的所有实例共享的属性和方法:python tutorial
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self,name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
此示例未向您显示的是,使用类方法,您可以在不经过实例的情况下在类上调用该方法!
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self,name):
self.name = name # instance variable unique to each instance
@classmethod
def isGoodBoy(cls):
return True # all dogs are good boys!
现在isGoodBoy
方法不需要访问狗的名字,因此它可以是一个类方法,并且可以反映所有实例;毕竟所有的狗都是好男孩(还有女孩!)。
但这可以告诉您更多!狗是好男孩吗?我们是否要求任何特定的狗成为好男孩?
>> Dog.isGoodBoy() # here we call the method on the class
True # debate settled!
现在再问其他四个问题;在处理类而不是对象时,最好使用类方法。您如何知道记录器实例在创建之前是否需要网络?这就是类方法和类变量的用途,并且该类的所有对象都具有相同的状态和行为。
现在,由于这在所有类之间共享,因此您现在还遇到其他问题,该类的每个实例都可能会修改类变量!这也意味着您可以在没有对象的情况下查询变量值!
假设您要在运行时从方法A切换到方法B。
class Foo:
upgrade = False
def a(self):
...
def b(self):
...
def run(self):
self.a() if self.upgrade else self.b()
现在Foo.upgrade = True
将为所有人切换内容!甚至最好通过运行Dog.kind = 'feline'
@classmethod定义以下方法是静态的,并且属于类而不是对象。
因此具有@classmethod的方法无法访问对象的任何值,但是可以在不初始化该类对象的情况下调用它。
用例为:
class Test:
@classmethod
def foo(cls,a,b):
# do smth
Test.foo(1,"abc")