您需要使用完整的类名来设置类变量。cls
indouble_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)
发生的事情是 in _initialize()
,cls
被设置为ObjectOne
or 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
所以现在_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
这将给出:
>>> obj_1 = ObjectOne()
cls.initialized = False
>>> obj_1.double_x()
2
>>> obj_2 = ObjectTwo()
cls.initialized = True
>>> obj_2.triple_x()
6
请注意,我打电话BaseObject._initialize()
以确保它cls
不是BasObject
子类。那么,在设置 和方法x
的时候还是直接引用来保证变量是直接设置在基类上的。上面例子的值在读取的时候仍然使用 ,在本地没有设置的时候使用类 MRO 在基类上查找。double_x
triple_x
BaseObject
x
cls
x