gpt4 book ai didi

Python - 如何从 __init__ 方法中引用类变量或方法?

转载 作者:太空狗 更新时间:2023-10-30 02:12:40 25 4
gpt4 key购买 nike

我在 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

我不明白什么?

最佳答案

您需要使用完整的类名来设置 类变量。 double_xtripple_x 中的 cls 将分别引用子类(ObjectOneObjectTwo ),并且在这些子类上设置属性将存储 变量,而不是改变类变量 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)

发生的事情是,在 _initialize() 中,cls 被设置为 ObjectOneObjectTwo,具体取决于您创建了什么实例,并且每个子类都获得了变量initializedx自己的 副本。

使用 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 作为目标来设置 initializedx 的初始值, 但 double_xtriple_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() 以确保 clsBasObject 而不是子类。然后,当设置 x double_xtriple_x 方法仍然直接引用 BaseObject以确保直接在基类上设置变量。当读取 x 的值时,上面的示例仍然使用 cls,它使用类 MRO 来查找 x未在本地设置时的基类。

关于Python - 如何从 __init__ 方法中引用类变量或方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14092983/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com