使用 UserDict 类有什么好处?
我的意思是,如果不是
,我真正得到的是什么class MyClass(object):
def __init__(self):
self.a = 0
self.b = 0
...
m = MyClass()
m.a = 5
m.b = 7
我将写下以下内容:
class MyClass(UserDict):
def __init__(self):
UserDict.__init__(self)
self["a"] = 0
self["b"] = 0
...
m = MyClass()
m["a"] = 5
m["b"] = 7
编辑:如果我理解正确的话,我可以在两种情况下都将新字段添加到运行时的对象中吗?
m.c = "Cool"
和
m["c"] = "Cool"
答案 0 :(得分:34)
UserDict.UserDict
没有实质性的附加值,因为正如@gs所提到的,你现在可以直接将dict
子类化 - 它只是为了向后兼容Python 2.1和更早版本,当内置时类型不能是子类。仍然,它保存在Python 3中(现在在collections
模块中的适当位置),因为the docs现在提到,
在Python 2中,这门课程的必要性 部分取代了能力 直接来自dict的子类;然而, 这个类可以更容易使用 因为基础字典是 可作为属性访问。
UserDict.DictMixin
非常方便 - 正如文档所说,
该模块定义了一个mixin,DictMixin, 定义所有字典方法 已经有最低限度的课程 映射界面。这很大 简化了编写需要的类 可以替代字典 (例如搁置模块)。
你对它进行了子类化,定义了一些基本方法(至少为__getitem__
,这对于只读映射而言是足够的,无法获取键或迭代;如果你需要这些能力,也可以keys
;可能__setitem__
,你有一个R / W映射,但没有删除项目的能力;添加__delitem__
以获得完整的功能,并可能出于性能原因覆盖其他方法),并得到一个完整的实现dict
丰富的API(update
,get
等)。 Template Method设计模式的一个很好的例子。
在Python 3中,DictMixin
消失了;您可以依靠collections.MutableMapping
(或仅collections.Mapping
进行R / O映射)来获得几乎相同的功能。它更优雅,虽然不是很方便(见this issue,关闭时“不会修复”;简短的讨论值得一读。)
答案 1 :(得分:7)
对dict进行子类化为您提供了dict的所有功能,例如if x in dict:
。如果你想扩展dict的功能,例如创建一个有序的dict,你通常会这样做。
BTW:在最新的Python版本中,您可以直接子类dict
,但不需要UserDict
。
答案 2 :(得分:3)
嗯,正如我刚刚发现的那样,从3.6版本开始肯定存在一些缺点。即,isinstance(o, dict)
返回False。
from collections import UserDict
class MyClass(UserDict):
pass
data = MyClass(a=1,b=2)
print("a:", data.get("a"))
print("is it a dict?:", isinstance(data, dict))
a: 1
is it a dict?: False
更改为class MyClass(dict):
,然后isinstance
返回True。
(pdb-进入函数/方法是一种准确了解它们如何工作的简单方法)
#assumes UserDict
di = MyClass()
import pdb
#pdb will have work if your ancestor is UserDict, but not with dict
#since it is c-based
pdb.set_trace()
di["a"]= 1
答案 3 :(得分:0)
正确覆盖dict
是很棘手的,而UserDict
则很容易。进行了一些讨论以将其从Python3中删除,但是我相信出于这个原因而保留了它。示例:
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
,所以没有那些缺点:
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}