我在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()
运行此模块时,我希望输出为:
cls.initialized = False
2
cls.initialized = True
6
但我得到的是:
cls.initialized = False
2
cls.initialized = False
3
我不明白什么?
有两个问题:首先,要调用类内的类方法,必须使用类的完整的名称:
BaseObject._initialize()
其次,每次创建ObjectOne
或ObjectTwo
的新实例时,都会覆盖其环境中的BaseObject.x
,因此其他人使用初始化的x
属性而不是更改的属性。若要解决此问题,必须更改两行:cls.x = cls.x *
2到BaseObject.x = cls.x * 2
以及
cls.x = cls.x * 3
到BaseObject.x = cls.x * 3
您需要使用完整的类名来设置类变量。^在}将分别引用子类(
double_x
和tripple_x
中{ObjectOne
和ObjectTwo
),并且在这些子类上设置属性将存储新的变量,而不是更改类变量BaseObject.x
。只有通过直接访问基类变量,才能改变基类变量。使用你的代码,我们得到:
在
_initialize()
中,cls
被设置为ObjectOne
或ObjectTwo
,这取决于您创建的实例,并且每个子类都有自己的变量initialized
和x
的副本。使用
BaseObject._initialize()
(以确保初始化BaseObject
,而不是子类)可以得到:所以现在
_initialize()
使用BaseObject
作为目标来设置initialized
和x
的初始值,但是double_x
和triple_x
仍然使用它们自己的子类来设置x
的new值,并且不通过BaseObject
共享该值。必须在特定基类上设置类变量的唯一选项是在all类方法中直接引用它:
这将给予:
注意,我调用了
BaseObject._initialize()
,以确保cls
是BasObject
,而不是子类。然后,当设置x
时,double_x
和triple_x
方法仍然直接引用BaseObject
,以确保变量直接在基类上设置。当读取x
的值时,上面的示例仍然使用cls
,当不在本地设置时,它使用类MRO在基类上查找x
。相关问题 更多 >
编程相关推荐