Python中UserDict类的优点

Python中UserDict类的优点,python,oop,Python,Oop,使用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

使用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"


子类化dict为您提供了dict的所有特性,如dict中的x:。如果您想扩展dict的功能,例如创建一个有序dict,通常会这样做

顺便说一句:在最近的Python版本中,您可以直接对
dict
进行子类化,您不需要
UserDict

自Python 2.2以来没有实质性的附加值,因为@gs提到,您现在可以直接对
dict
进行子类化——它的存在只是为了向后兼容Python 2.1及更早版本,当内置类型不能是子类时。尽管如此,它仍然保存在Python3中(现在它在
集合
模块中的适当位置),因为,正如现在提到的

这门课的需求一直在增加 部分被以下能力所取代 直接来自dict的子类;然而, 这个类更容易使用 因为底层字典是 可作为属性访问

Python2中的UserDict.DictMixin非常方便——正如文档所说

该模块定义了一个mixin,DictMixin, 定义的所有字典方法 已具有最小值的类 映射接口。这非常重要 简化编写需要 可替代词典 (如搁置模块)

你可以给它分类,定义一些基本的方法(至少
\uuuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu基于性能原因的其他方法),并获得
dict
丰富API的完整实现(
update
get
,等等)。这是设计模式的一个很好的示例


在Python3中,
DictMixin
已经不存在了;您可以通过依赖
collections.MutableMapping
来获得几乎相同的功能(或者对于R/O映射只使用
collections.Mapping
)。它稍微优雅了一点,但没有那么方便(请参见,以“will not fix”结尾;简短的讨论值得一读).

正如我刚刚发现的,从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))

不是口授! 更改为
class MyClass(dict):
isinstance
返回True

然而,使用UserDict,您可以逐步实现它。 (pdb分解成函数/方法是一种简单的方法,可以准确地了解它们是如何工作的)


正确覆盖
dict
是一件棘手的事情,而
UserDict
则让它变得简单。关于从Python3中删除它,曾进行过一些讨论,但我相信它是出于这个原因保留的。例如:

类MyDict(dict):
定义设置项(自身、键、值):
超级()
d=MyDict(a=1,b=2)#输出MyDict.uu_usetitem_uu_uu未调用
d、 更新(c=3)#输出MyDict.uu设置项uu_u_u未调用
好!
印刷体(d){'a':1,'b':2,'c':3,'d':40}
UserDict
inherit
collections.abc.MutableMapping
,因此没有这些缺点:

类MyDict(collections.UserDict):
定义设置项(自身、键、值):
超级()
d=MyDict(a=1,b=2)#好:MyDict.u_usetitem_uu_u_u正确调用
d、 更新(c=3)#良好:MyDict.u_usetitem_uu_u_u正确调用
好的
印刷体(d){'a':10,'b':20,'c':30,'d':40}

自2009年以来,python 3中的东西发生了一些变化,DictMixin又回来了:-尽管对于大多数用途来说,确实建议使用可变映射。这仍然有效吗?阅读“流畅的python”,作者建议对UserDict进行子类化,因为“主要注意事项:内置代码(用C编写)不调用特殊(魔法)本书涵盖了3.x,但这个警告是否也适用于2.7?@Stefano:Python 3的标准库中现在没有,而且我很确定从来没有任何DictMixin。您提供的链接当时是指向Python 2.7.2文档(目前是404)的链接@Kundor你似乎是对的,尽管我一直在想为什么我当时会发布一个py2文档链接。py3中有一个,可能我有点困惑。感谢你指出这一点!我在官方Python 3文档中看到了UserDict,但没有看到任何关于可变映射的内容。很可能,答案已经过时了。
    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

#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