使用UserDict类有什么好处?
我的意思是,如果不是,我真的得到了什么
class MyClass(object):
def __init__(self):
self.a = 0
self.b = 0
...
m = MyClass()
m.a = 5
m.b = 7
Run Code Online (Sandbox Code Playgroud)
我会写以下内容:
class MyClass(UserDict):
def __init__(self):
UserDict.__init__(self)
self["a"] = 0
self["b"] = 0
...
m = MyClass()
m["a"] = 5
m["b"] = 7
Run Code Online (Sandbox Code Playgroud)
编辑:如果我理解正确,我可以在两种情况下都在运行时向对象添加新字段?
m.c = "Cool"
Run Code Online (Sandbox Code Playgroud)
和
m["c"] = "Cool"
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 34
UserDict.UserDict自从Python 2.2以来没有实质性的附加值,因为正如@gs所提到的,你现在可以dict直接子类- 它只是为了向后兼容Python 2.1及更早版本,当内置类型不能是子类时.尽管如此,它仍保留在Python 3中(现在在collections模块中的适当位置),正如文档现在提到的那样,
直接从dict子类化的能力部分取代了对这个类的需求; 但是,这个类可以更容易使用,因为底层字典可以作为属性访问.
UserDict.DictMixin在Python 2中,非常方便 - 正如文档所说,
该模块定义了一个mixin,DictMixin,为已经具有最小映射接口的类定义所有字典方法.这极大地简化了编写需要替代字典的类(例如搁置模块).
你对它进行了子类化,定义了一些基本的方法(至少__getitem__,这对于只读映射而言是足够的,没有获取键或迭代的keys能力;如果你需要这些能力;可能__setitem__,你有一个没有能力的R/W映射删除项目;添加__delitem__完整功能,并可能出于性能原因覆盖其他方法),并获得dict丰富的API(update,get等等)的完整实现.模板方法设计模式的一个很好的例子.
在Python 3中,DictMixin已经不见了; 您可以通过依赖(或仅用于R/O映射)获得几乎相同的功能.它更优雅,虽然不是很方便(看到这个问题,关闭时"不会修复";简短的讨论值得一读).collections.MutableMappingcollections.Mapping
对dict进行子类化为您提供了dict的所有功能,例如if x in dict:.如果要扩展dict的功能,例如创建有序的dict,通常会这样做.
顺便说一句:在最近的Python版本中,你可以dict直接子类化,你不需要UserDict.
正确覆盖很困难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}
Run Code Online (Sandbox Code Playgroud)
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}
Run Code Online (Sandbox Code Playgroud)
嗯,正如我刚刚发现的那样,从 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))
Run Code Online (Sandbox Code Playgroud)
a: 1
is it a dict?: False
Run Code Online (Sandbox Code Playgroud)
更改为class MyClass(dict):并isinstance返回 True。
(pdb-ing 到函数/方法中是了解它们如何工作的简单方法)
#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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17562 次 |
| 最近记录: |