簡體   English   中英

Python - 如何從__init__方法中引用類變量或方法?

[英]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_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 ,具體取決於您創建的實例,並且每個子類都有自己 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_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而不是子類。 然后,當設置 xdouble_xtriple_x方法仍然直接引用BaseObject以確保直接在基類上設置變量。 讀取 x的值時,上面的例子仍然使用cls ,當沒有在本地設置時,它使用類MRO在基類上找到x

你有兩個問題。首先,為了在類中調用類方法,你必須使用類的COMPLETE名稱: BaseObject._initialize()第二,每次你創建一個ObjectOneObjectTwo的新實例時,您在其環境中覆蓋BaseObject.x ,因此其他人使用初始化的x屬性而不是更改的屬性。要修復此問題,您必須更改兩行:

cls.x = cls.x * 2到BaseObject.x = cls.x * 2

cls.x = cls.x * 3BaseObject.x = cls.x * 3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM