2009-05-25 79 views
16

比方說,我有下面的類在子類擴展一個類屬性的一個巧妙的辦法

class Parent(object): 
    Options = { 
     'option1': 'value1', 
     'option2': 'value2' 
    } 

和被稱爲兒童

class Child(Parent): 
    Options = Parent.Options.copy() 
    Options.update({ 
     'option2': 'value2', 
     'option3': 'value3' 
    }) 

我希望能夠覆蓋或添加選項子孩子班。我正在使用的解決方案。但我相信有一個更好的方法來做到這一點。


編輯

我不想爲類的屬性,因爲我有沒有選擇其他類的屬性,我寧願保持所有選項在一個地方添加選項。這只是一個簡單的例子,實際的代碼比這更復雜。

+0

的方式爲什麼不出貨父類的方法複製/更新邏輯?如果你把它放在`__init__`中,並且總是在子類`__init__`的末尾調用`super().__ init __()`,就像你應該這樣做,它應該可以工作。 – asmeurer 2013-06-16 20:56:25

回答

8

一種方法是使用關鍵字參數與dict指定其他鍵:

Parent.options = dict(
    option1='value1', 
    option2='value2', 
) 

Child.options = dict(Parent.options, 
    option2='value2a', 
    option3='value3', 
) 

如果你想更大膽的嘗試,然後使用描述協議,您可以創建一個代理對象這將封裝查找。 (只需將owner .__ mro__從owner屬性移動到__get __(self,instance,owner)方法)。甚至更有趣,進入可能不是一個好主意的領域,metaclasses /類裝飾。

4

爲什麼不直接使用類屬性?

class Parent(object): 
    option1 = 'value1' 
    option2 = 'value2' 

class Child(Parent): 
    option2 = 'value2' 
    option3 = 'value3' 
+0

你,贏了。打我20秒:) – SpliFF 2009-05-25 16:41:33

+0

我更喜歡在一個屬性中保留選項,因爲我有其他類屬性不是選項。 – 2009-05-25 16:50:39

+0

您可以用一個前綴標記特殊的attirbutes,例如`opt_foo`和`opt_bar`,然後訪問例如`[getattr(self,x)for x in dir(self)if x。startswith(「opt _」)]` – 2012-11-05 15:03:29

2
class ParentOptions: 
    option1 = 'value1' 
    option2 = 'value2' 

class ChildOptions(ParentOptions): 
    option2 = 'value2' 
    option3 = 'value3' 

class Parent(object): 
    options = ParentOptions() 

class Child(Parent): 
    options = ChildOptions() 
21

語義上等同於你的代碼,但可以說是整潔:

class Child(Parent): 
    Options = dict(Parent.Options, 
     option2='value2', 
     option3='value3') 

記住,「生活是沒有括號更好」,並通過調用dict明確你常常可以避開括號(和額外的引號是常數標識符關鍵字類似的字符串)。

更多細節請http://docs.python.org/library/stdtypes.html#dict - 關鍵位是「如果兩個在位置參數和作爲關鍵字參數指定的密鑰,與關鍵字相關聯的值被保留的」,即關鍵字ARGS 倍率鍵 - 值的關聯在位置arg中,就像update方法可以讓你覆蓋它們)。

6

想更多地瞭解它後,並感謝@SpliFF建議這是我想出了:

class Parent(object): 
    class Options: 
     option1 = 'value1' 
     option2 = 'value2' 


class Child(Parent): 
    class Options(Parent.Options): 
     option2 = 'value2' 
     option3 = 'value3' 

我還是開到更好的解決方案雖然。

2

下面是使用元類

class OptionMeta(type): 
    @property 
    def options(self): 
     result = {} 
     for d in self.__mro__[::-1]: 
      result.update(getattr(d,'_options',{})) 
     return result 

class Parent(object): 
    __metaclass__ = OptionMeta 
    _options = dict(
     option1='value1', 
     option2='value2', 
     ) 

class Child(Parent): 
    _options = dict(
     option2='value2a', 
     option3='value3', 
     ) 

print Parent.options 
print Child.options 
相關問題