2012-11-15 102 views
31

我想要一個子類修改它從父類繼承的類變量。Python中的繼承類變量修改

我願做線沿線的東西:

class Parent(object): 
    foobar = ["hello"] 

class Child(Parent): 
    # This does not work 
    foobar = foobar.extend(["world"]) 

,並最好有:

Child.foobar = ["hello", "world"] 

我可以這樣做:

class Child(Parent): 
    def __init__(self): 
     type(self).foobar.extend(["world"]) 

但後來我每次實例Child的一個實例,「world」被附加到列表中,這是不希望的。我會進一步修改它:

class Child(Parent): 
    def __init__(self): 
     if type(self).foobar.count("world") < 1: 
      type(self).foobar.extend(["world"]) 

但這仍是一個黑客,因爲它的工作原理之前,我必須實例子的一個實例。

有沒有更好的方法?

回答

35

假設你想在子類中單獨列出,不修改父類的列表(這似乎毫無意義的,因爲你可以只修改的地方,或者把期望值那裏開始):

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

請注意,這可以獨立於繼承,這可能是一件好事。

+1

這是非常輝煌和簡單!另外,如果子屬性的起始值必須與父屬性相同,則使用'from copy import deepcopy; foob​​ar = deepcopy(Parent.foobar)' – zen11625

16

你不應該在你的類變量中使用可變值。在實例設置這樣的值,而不是使用__init__()實例初始化:

class Parent(object): 
    def __init__(self): 
     self.foobar = ['Hello'] 

class Child(Parent): 
    def __init__(self): 
     super(Child, self).__init__() 
     self.foobar.append('world') 

否則會發生什麼,該foobar清單不僅是實例共享,但與亞類。

在任何情況下,即使您希望通過可變類變量在實例之間共享狀態,您也必須避免修改父類的可變值;只有分配的名字將創建一個新的變量:

class Parent(object): 
    foobar = ['Hello'] 

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

其中用於Child類創建一個新的foobar變量。通過使用賦值,您創建了一個新的列表實例,並且可變形不受影響。

在這種情況下請小心嵌套mutables;如有必要,使用copy模塊創建深層副本。