jon*_*omo 4 python class-method
我在python模块中有一个对象层次结构,如下所示:
class BaseObject(object):
initialized = False
def __init__(self):
self._initialize()
@classmethod
def _initialize(cls):
print "cls.initialized = "+str(cls.initialized)
if not cls.initialized:
cls.x = 1
cls.initialized = True
class ObjectOne(BaseObject):
@classmethod
def double_x(cls):
cls.x = cls.x * 2
print cls.x
class ObjectTwo(BaseObject):
@classmethod
def triple_x(cls):
cls.x = cls.x * 3
print cls.x
if __name__ == '__main__':
obj_1 = ObjectOne()
obj_1.double_x()
obj_2 = ObjectTwo()
obj_2.triple_x()
Run Code Online (Sandbox Code Playgroud)
当我运行这个模块时,我希望输出为:
cls.initialized = False
2
cls.initialized = True
6
Run Code Online (Sandbox Code Playgroud)
但我得到的是:
cls.initialized = False
2
cls.initialized = False
3
Run Code Online (Sandbox Code Playgroud)
我不明白什么?
您需要使用完整的类名来设置类变量.clsin double_x和tripple_x将引用子类(ObjectOne和ObjectTwo分别),并在这些子类上设置属性将存储新变量,而不是更改类变量BaseObject.x.您只能通过直接访问它们来更改基类变量.
使用您的代码,我们得到:
>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = False
>>> obj_2.triple_x()
3
>>> BaseObject.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'BaseObject' has no attribute 'x'
>>> BaseObject.initialized, ObjectOne.initialized, ObjectOne.x, ObjectTwo.initialized, ObjectTwo.x
(False, True, 2, True, 3)
Run Code Online (Sandbox Code Playgroud)
发生了什么事是,在_initialize(),cls被设置为ObjectOne或ObjectTwo,这取决于你创造了什么实例,每个子类得到了他们自己的变量副本initialized和x.
使用BaseObject._initialize()(确保BaseObject初始化,而不是子类)给出:
>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = True
>>> obj_2.triple_x()
3
>>> BaseObject.x, ObjectOne.x, ObjectTwo.x
(1, 2, 3)
>>> BaseObject.initialized
True
>>> 'x' in ObjectOne.__dict__
True
>>> 'initialized' in ObjectOne.__dict__
False
>>> 'initialized' in ObjectTwo.__dict__
False
Run Code Online (Sandbox Code Playgroud)
所以现在_initialize()使用BaseObject作为目标设定initialized和初始值x,但double_x并triple_x仍在使用自己的子类设置的新的价值x,而不是通过共享该值BaseObject.
在特定基类上设置类变量的唯一选择是直接在所有类方法中引用它:
class BaseObject(object):
initialized = False
def __init__(self):
BaseObject._initialize()
@classmethod
def _initialize(cls):
print "cls.initialized = "+str(cls.initialized)
if not cls.initialized:
cls.x = 1
cls.initialized = True
class ObjectOne(BaseObject):
@classmethod
def double_x(cls):
BaseObject.x = BaseObject.x * 2
print cls.x
class ObjectTwo(BaseObject):
@classmethod
def triple_x(cls):
BaseObject.x = BaseObject.x * 3
print cls.x
Run Code Online (Sandbox Code Playgroud)
这会给:
>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = True
>>> obj_2.triple_x()
6
Run Code Online (Sandbox Code Playgroud)
需要注意的是我打电话BaseObject._initialize(),以确保cls是BasObject和不是一个子类别.然后,当设定 x了double_x和triple_x方法仍然直接引用BaseObject,以确保该变量上直接设置的基类.当读取x上面示例的值仍然使用时cls,它在x本地未设置时使用类MRO 在基类上查找.