子类dict:UserDict,dict还是ABC?

2024-05-13 00:33:09 发布

您现在位置:Python中文网/ 问答频道 /正文

UserDictdictABC之间有什么区别?推荐哪一种?文件似乎反对UserDict

而且,似乎UserDict的update()会使用我的setitem方法,而dict不会?如果我想要自定义的setitemgetitem函数,那么哪些方法是重写的关键?

使用ABC我必须实现所有方法,因为它不提供默认实现?

我想做一个dict来做两件事:

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

那么UserDictdictABC中哪一个最适合我这样做呢?


Tags: 文件方法函数数据库sqliteupdate两件事dict
3条回答

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

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

ABC没有提供存储实际数据的方法,只是提供了一个接口,其中包含一些方法的默认实现。但是,这些默认实现将调用自定义的__getitem____setitem__。必须使用内部dict来保存数据,并实现所有抽象方法:__len____iter____getitem____setitem____delitem__

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

总而言之:

  • 可变映射定义接口。将其子类化以创建类似于dict的对象。完全取决于你是否以及如何存储数据。
  • UserDict是使用内部“real”dict作为存储的MutableMapping的实现。如果希望使用类似dict的存储集合,但重写由dict公开的某些方法,这可能是一个很好的起点。但请确保阅读代码以了解基本方法是如何实现的,以便在重写方法时保持一致。
  • dict是“真实的事物”。如果您想扩展接口,可以将其子类化。重写方法以执行自定义操作可能会很危险,因为通常有多种访问数据的方法,而且最终可能会出现不一致的API。

基于秘密Recipes of the Python Ninja

除了常规的字典操作之外,UserDict唯一的特殊之处是一个属性:

data: A real dictionary to hold the contents of the UserDict class

要访问字典中的项,必须迭代它们或调用items()。虽然UserDict实例支持相同的方法,但items()返回的视图明显不同:

  >>> from collections import UserDict
  >>> a = UserDict(a=1)
  >>> d = dict(d=3)  # regular dictionary for comparison

  >>> for k in d:
  ...     print(k, d[k])
  ... 
  d 3
  >>> d.items()
  dict_items([('d', 3)])
  >>> for k in a:
  ...     print(k, a[k])
  ... 
  a 1
  >>> a.items()
  ItemsView({'a': 1})

注意,dictionary对象返回键/值的元组。UserDict返回一个实际的dictionary对象。根据您所做的操作,这种差异可能很重要,使用data属性访问字典的能力也很重要。

不要使用UserDict类——您不需要它。正如文档所说,您可以直接对dict进行子类划分。

但是,您仍然需要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__使用您的update

相关问题 更多 >