2015-06-07 115 views
3

一個簡單的例子:繼承和聚合類屬性

class A: 
    attr = {'a': 1} 

class B(A): 
    attr = {'b': 2} #overrides A.attr 

我想是聚集字典的方法。我只能想到這些選項:

  1. 忽略那種令人不安的感覺並且手工複製所有東西。
  2. 手動添加的字典:

    class B(a): 
        attr = dict(list(six.iteritems(A.attr)) + list(six.iteritems({ 
         'b': 2 
        }))) 
    

    注意'b': 2一定要來第二所以它的按鍵影子A的。

    這必須明確引用A是否有某種方式可以通過super得到此結果)。它也需要手動應用這種微遺傳。

  3. 這也是可以用元類實現的東西。我見過它done in DeclarativeFieldsMetaclass in django。 這個想法是讓metaclass爲特定屬性處理字典合併。

    這是更多的工作。另外,因爲它引入了通常不會發生在Python中的魔法,所以這可能被認爲是不好的選擇。除非有必要避免衝突,否則我也寧願不使用元類。

    一個主要優勢是用戶不需要手動聚合屬性數據。

還有別的辦法嗎?

我想知道別人怎麼看待每種方法的良好編程習慣。

在我的情況下,我使用的是MultiModelForm from django-betterforms,只有幾個ModelForm s的基本形式,但想擴展它。我不認爲繼承的類應該需要複製ModelForm s在父級的form_classes屬性中。

是否應該由用戶來管理繼承,如選項2中所示,還是MultiModelForm應該像選項3中那樣通過元類自動處理?每個選項我還沒有討論過其他問題嗎?

+1

[在Python 3.5(https://www.python.org/dev/peps/pep-0448/),你就可以做'attr = {** A.attr,'b':2}'。 – user2357112

回答

6

可以使用dictionary.update()功能,這將增加一個新的字典現有

>>> class A: 
...  attr = {'a': 1} 
... 
>>> class B(A): 
...  attr = dict(A.attr) 
...  attr.update({'b' : 2 }) 
... 
>>> 
>>> A.attr 
{'a': 1} 
>>> B.attr 
{'a': 1, 'b': 2} 

它做什麼呢?

  • attr = dict(A.attr)返回從A.attr一個新的字典。因爲如果我們寫

    attr = A.attr 
    

    我們最終會更新attrA的類,而不是B類的這一點很重要。

  • attr.update({'b' : 2 })通過添加新的字典{'b' : 2 }來更新B.attr

4

這個工作對我來說:

class A: 
    attr = {'a': 1} 

class B(A): 
    attr = dict({'b': 2}.items() + A.attr.items()) 
+0

你說得對,它也是。我一直認爲這只是python 3。雖然它會扭轉添加的順序。 – jozxyqk

+0

@jozxyqk:它實際上只是Python * 2 *;在Python 3中,'items'返回一個視圖,並且dict視圖不支持添加。如果你真的想要的話,你可以改變它以適應Python 3。 – user2357112