子类dict:UserDict,dict还是ABC?

时间:2011-08-22 13:44:30

标签: python subclass

UserDictdictABC之间有什么区别?推荐哪一个?文档似乎已弃用UserDict

似乎UserDict的update()会使用我的setitem方法,而dict则不会?在我想要自定义setitemgetitem功能的情况下,哪些方法对于覆盖真的很重要?

使用ABC s我必须绝对实现所有方法,因为它没有提供默认实现吗?

我想制作一个dict做两件事:

  • intern()所有键和值
  • 将一些值存储在SQLite数据库中

那么UserDictdictABC哪个最能让我这样做?

3 个答案:

答案 0 :(得分:45)

如果您想要一个实际保存数据的自定义集合,则子类 dict 。如果您想扩展接口(例如,添加方法),这将非常有用。

但是,没有任何内置方法会调用您的自定义__getitem__ / __setitem__。如果您需要完全控制这些,请创建一个实现collections.MutableMapping抽象基类的自定义类。

ABC不提供存储实际数据的方法,只提供具有某些方法的默认实现的接口。但是,这些默认实现会调用您的自定义__getitem____setitem__。您必须使用内部dict来保存数据,并实现所有抽象方法:__len____iter____getitem____setitem__和{{ 1}}。

来自__delitem__模块的类UserDict(在Python 2中,模块也称为collections)是内部UserDict的包装器,实现{ {1}} ABC。如果要自定义dict的行为,则此实现可能是一个起点。

总结:

  • MutableMapping 定义界面。对此进行子类化以创建类似于MutableMapping的内容。如果以及如何存储数据,完全取决于您。
  • UserDict 是使用内部“真实”dict作为存储的dict的实现。如果你想要一个类似dict的存储集合但是覆盖MutableMapping公开的一些方法,这对你来说可能是一个很好的起点。但请务必阅读代码以了解基本方法的实现方式,以便在覆盖方法时保持一致。
  • dict 是“真实的东西”。如果要扩展接口,则对其进行子类化。覆盖自定义事物的方法可能很危险,因为通常有多种方法来访问数据,最终可能会出现不一致的API。

答案 1 :(得分:1)

不要使用UserDict类 - 您不需要它。正如文档所说,您可以直接将dict子类化。

但是,对于DictMixin

,您仍然需要UserDict模块

注意: 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__

答案 2 :(得分:1)

我从这里找到了dictuserdict之间的区别的一个示例:https://dev.to/0xbf/customize-your-own-dictionary-python-tips-5b47

如果您从__delitem__覆盖dict,则此方法仅适用于del方法,而不适用于pop

发生这种情况的原因是因为Python的内置dict有一些内联优化,导致弹出窗口不调用 delitem

这不是很直观。

但是,当您覆盖userdict的{​​{1}}时,__delitem__del都会受到影响。