首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >子类dict: UserDict,dict还是ABC?

子类dict: UserDict,dict还是ABC?
EN

Stack Overflow用户
提问于 2011-08-22 13:44:29
回答 5查看 16.7K关注 0票数 53

UserDictdictABC有什么区别,推荐哪一个?这些文档似乎反对UserDict

而且,看起来UserDict的update()会使用我的setitem方法,而dict不会吗?考虑到我想要定制的setitemgetitem函数,哪些方法才是重写的关键?

对于ABC,我必须实现所有的方法,因为它没有提供默认的实现?

我想做一个做两件事的dict

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

那么,UserDictdictABC中哪一个最允许我这样做呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-08-22 13:58:51

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

但是,所有内置方法都不会调用自定义的__getitem__ / __setitem__。如果需要对这些类进行完全控制,则创建一个实现collections.MutableMapping抽象基类的自定义类。

ABC不提供存储实际数据的方法,只为某些方法提供默认实现的接口。然而,这些默认实现将调用您的自定义__getitem____setitem__。您必须使用内部dict来保存数据,并实现所有抽象方法:__len____iter____getitem____setitem____delitem__

来自UserDict模块的类collections (在Python2中,该模块也称为UserDict )是一个内部dict的包装器,实现MutableMapping ABC。如果您想要自定义dict的行为,这个实现可能是一个起点。

总结如下:

  • MutableMapping定义了接口。子类来创建类似于dict的东西。这完全取决于你是否和如何存储数据。
  • UserDict是使用内部“真实”dict作为存储的MutableMapping的实现。如果您想要一个类似块的存储集合,但是要覆盖dict公开的一些方法,那么这可能是一个很好的起点。但是,请确保阅读代码以了解基本方法是如何实现的,以便在重写方法时保持一致。
  • dict是“真实的东西”。如果要扩展接口,请将其子类化。重写自定义操作的方法可能很危险,因为通常有多种访问数据的方法,而且您可能会得到一个不一致的API。
票数 69
EN

Stack Overflow用户

发布于 2020-10-20 17:46:05

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

如果从__delitem__重写dict,则这将只应用于del方法,而不应用于pop

之所以会发生这种情况,是因为Python的内置dict有一些内联优化,这导致pop没有调用delitem

这是很不直观的。

然而,当您覆盖userdict__delitem__时,delpop都会受到影响。

票数 2
EN

Stack Overflow用户

发布于 2022-04-21 11:24:25

当您需要定制dict时,UserDict通常是最简单的选择。

正确地覆盖dict是很棘手的,而UserDict则使它变得简单。有一些关于从Python3中删除它的讨论,但我相信它是出于这个原因而保留的。示例:

代码语言:javascript
复制
class MyDict(dict):

  def __setitem__(self, key, value):
    super().__setitem__(key, value * 10)


d = MyDict(a=1, b=2)  # Oups MyDict.__setitem__ not called
d.update(c=3)  # Oups MyDict.__setitem__ not called
d['d'] = 4  # Good!
print(d)  # {'a': 1, 'b': 2, 'c': 3, 'd': 40}

UserDict继承了collections.abc.MutableMapping,因此没有这些缺点:

代码语言:javascript
复制
class MyDict(collections.UserDict):

  def __setitem__(self, key, value):
    super().__setitem__(key, value * 10)


d = MyDict(a=1, b=2)  # Good: MyDict.__setitem__ correctly called
d.update(c=3)  # Good: MyDict.__setitem__ correctly called
d['d'] = 4  # Good
print(d)  # {'a': 10, 'b': 20, 'c': 30, 'd': 40}

直接子类collections.abc.MutableMapping除了需要覆盖__len____iter__,而子类UserDict则容易得多。

不过,有一点要注意的是,UserDictMutableMapping,而不是dict

代码语言:javascript
复制
assert not isinstance(collections.UserDict(), dict)
assert isinstance(collections.UserDict(), collections.abc.MutableMapping)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7148419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档