簡體   English   中英

Python類繼承 - Base由子類修改

[英]Python class inheritance - Base is modified by a subclass

假設我有一個名為Test的類,帶有屬性項。 然后我創建一個名為Best的子類。 其中有一個修改classes屬性項的方法。 但它甚至修改了Testitems ,我只修改了Best items

class Test():
    items = []

class Best(Test):
    def method(self):
        type(self).items.append("a test")

>>> Best().method()
>>> Best.items
["a test"]
>>> Test.items 
["a test"]            # This is what I don't want.

您已將items聲明為超類本身的屬性,因此Test的所有實例及其子類將共享相同的列表。 而是在Test的__ init __方法中聲明它,因此每個實例有一個列表。

在Best中,只需附加到self.items ,只會更新Best實例的列表。

class Test(object):
    def __ init __(self)
        self.items = []

class Best(Test):    # Best must inherit from Test
    def method(self):
        self.items.append("a test")

在Python中,您可以通過使用“私人”成員獲得您所要求的內容......

class Base(object):
    def __init__(self):
        self.__mine = 42  # note the double underscore
    def baseMethod(self):
        return self.__mine

class Derived(Base):
    def __init__(self):
        Base.__init__(self)
        self.__mine = 99

    def derivedMethod(self):
        return self.__mine

obj = Derived()
print(obj.baseMethod(), obj.derivedMethod()) ## ==> 42, 99

這是有效的,因為在編譯時 Python將在編譯Base時用_Base__mine替換名稱__mine ,在編譯Derived時用_Derived__mine

但請注意,在Python中,雖然根據我的經驗這是可行的,但它並不經常使用。 由於“鴨子打字”和授權,在許多情況下派生一個類是不需要的,這在C ++或Java等語言中是不可能的。

你的Best類正在修改Test (我認為它應該繼承),因為Best沒有自己的items列表。 當您訪問Best.items ,您將訪問從中繼承的列表(即來自Test類)。 如果你想要一個不同的列表,你需要在子類Best顯式創建它:

class Best(Test):
    items = [] # hide the inherited list with our own list

    # ...

唯一可行的方法是在子類上創建一個新items - 這個新列表還來自哪里? type(self)也是多余的。 查找機制在類上查找屬性,如果它無法在實例上找到屬性。 更好的是,如果您不需要實例,則將該方法聲明為類方法。

例如。

class Test:
    items = []
    @classmethod
    def method_test(cls):
        cls.items.append('test')

class Best(Test):
    items = []
    @classmethod
    def method_best(cls):
        cls.items.append('best')

Test.method_test()

assert Test.items == ['test']
assert Best.items == []

Test.items = []
Best.method_test()
Best.method_best()

assert Test.items == []
assert Best.items == ['test', 'best']

需要注意的是method_test工作在Best類從調用時Best的類。

您的代碼不符合您的描述。

首先, Best不是Test的子類。

對於另一個Best.method()產生

NameError: name 'self' is not defined

itemsTest類屬性。

t = Test()
t.items.append(1)

改變Test.items

如定義的B.items給出一個AttributeError

即使我改變了:

class Best():
    def method(self):
        ...

Best.method()沒有運行; method是一個實例方法。 我需要使用Best().method() 但后來我得到了items AttributeError

 class Best(Test):
    def method(self):
        ...

做你想做的事。 Best().method()修改Test.items - 因為Test類屬性與子類共享。

如其他答案所示,只需定義Best items ,即可將其值與Test類屬性分離

 class Best(Test):
     items = ['other']
     ...

暫無
暫無

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

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