[英]How can I reference the __init__ method of a derived class in Python from the base class?
[英]Python - how can I reference a class variable or method from within the __init__ 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()
當我運行這個模塊時,我希望輸出為:
cls.initialized = False
2
cls.initialized = True
6
但我得到的是:
cls.initialized = False
2
cls.initialized = False
3
我不明白什么?
您需要使用完整的類名來設置類變量。 double_x
和tripple_x
cls
將引用子類(分別為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)
發生了什么,在_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
所以現在_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
, double_x
和triple_x
方法仍然直接引用BaseObject
以確保直接在基類上設置變量。 當讀取 x
的值時,上面的例子仍然使用cls
,當沒有在本地設置時,它使用類MRO在基類上找到x
。
你有兩個問題。首先,為了在類中調用類方法,你必須使用類的COMPLETE名稱: 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.