2011-08-22 63 views
35

UserDict,dictABC之間的區別和推薦哪一個?該文檔似乎不贊成UserDict子類字典:UserDict,dict或ABC?

另外它似乎UserDict的update()將使用我的setitem方法,而dict不?哪一種方法真的不可或缺,因爲我想自定義setitemgetitem函數?

隨着ABC s我必須實現絕對所有的方法,因爲它沒有提供默認的實現?

我想打一個dict做兩件事情:

  • intern()所有鍵和值
  • 存放一些值的SQLite數據庫

所以其中UserDictdictABC最好讓我這樣做?

+0

但是至少有一些ABCs對於簡化不是基於內置類型的實現也很有用,正如同一部分的這段代碼所示:'幾個ABCs也可用作mixin,使它更容易開發支持容器API的類。例如,要編寫支持完整設置API的類,只需提供三種底層抽象方法:__contains __(),__iter __()和__len __()。 ABC提供剩餘的方法,如__和__()和isdisjoint()' – delnan

+1

如果你想測試是否是'dict',使用'isistance(x,dict)'。如果你想測試它是某種映射,使用'isinstance(x,映射)'。這是ABCs的用途。它們僅在每種映射使用'Mapping.register()'或直接對其進行子類化時纔有用。是的,這**是** ABC的主要目的。 –

回答

36

如果你想自定義集合,實際上保存數據,子類字典。如果你想要擴展接口(例如,添加方法),這是特別有用的。

無的內置方法將調用您的自定義__getitem__/__setitem__,雖然。如果您需要對這些控件進行完全控制,請創建一個實現類抽象基類的自定義類。

的ABC不提供用於存儲實際數據,僅與默認實現一些方法的接口的裝置。但是,這些默認實現將調用您的自定義__getitem____setitem__。您將不得不使用內部dict來保存數據,並實施所有抽象方法:__len__,__iter__,__getitem__,__setitem____delitem__

collections模塊(在Python 2中,模塊被稱爲UserDict以及)類UserDict是一個內部dict周圍的包裝,實施MutableMapping ABC。如果你想自定義dict的行爲,這個實現可能是一個起點。

總結:

  • MutableMapping定義的接口。子類創建一個像dict一樣的東西。如果您以及如何存儲數據,完全取決於您。
  • UserDict是使用內部「真實」dict作爲存儲的MutableMapping的實現。如果你想要一個類似字典的存儲集合,但覆蓋dict公開的一些方法,這對你來說可能是一個很好的起點。但請確保閱讀代碼以瞭解基本方法的實現方式,以便在重寫方法時保持一致。
  • 字典是「真實的東西」。如果您想要擴展的子接口。重寫自定義事物的方法可能是危險的,因爲通常有多種訪問數據的方式,並且最終會導致不一致的API。
+0

謝謝。從之前的文章中,我瞭解了Mixins,現在我意識到ABC提供了默認的實現方式。自己提供一個數據變量是一個小問題,所以我想我會習慣ABC。 – Gerenuk

+0

@agf:即使'DictMixin'也要求你實現5個基本方法 –

+0

@agf:'userdict'模塊在Python 3.0中不見了,這就是爲什麼我說它已被棄用。 http://www.python.org/dev/peps/pep-3108/(Quote:「不那麼有用,因爲類型可以是超類,有用的位移動到'collections'模塊。」) –

2

不要使用UserDict類 - 你不需要它。正如文檔所說,你可以直接繼承dict

但是,你仍然希望UserDict模塊,爲DictMixin

注:DictMixin,雖然沒有正式棄用,已經在Python 3中刪除,並且它在你使用collections.MutableMapping的文檔建議。但是,這有一個缺點 - 需要實現更多的字典界面 - __delitem____getitem____iter____len____setitem__。使用DictMixin,你可以實現你想改變的那個,其餘的使用默認實現。

from UserDict import DictMixin 

class MyDict(DictMixin, dict): 
    def __setitem__(self, key, value): 
     print key, value # just an example 
     # use intern(key) or whatever here 
     dict.__setitem__(self, key, value) # or 
     # super(MyDict, self).__setitem__(key, value) 

m = MyDict() 

m['a'] = 'b' 
# a b 
m.update({'a': 'c'}) 
# a c 

它會自動讓update使用__setitem__你想要的。

+3

>從Python版本2.6開始,建議使用collections.MutableMapping而不是DictMixin。 – cwallenpoole

+3

@agf:你錯了。 'UserDict'模塊已被棄用,不應使用。如何將'UserDict.DictMixin'作爲混合使用比使用'collections.MutableMapping'更容易混合?在這兩種情況下,您只需要覆蓋'__setitem __()'。 –

+0

@agf:整個模塊在Python 3.x中不見了。 –