在frozendict
was rejected期间,相关的类types.MappingProxyType
已添加到python 3.3中的公共API。
我理解MappingProxyType
只是基础dict
的包装,但尽管不是它在功能上等同于frozendict
吗?
换句话说,原始PEP 416 frozendict
与此之间存在实质性差异:
from types import MappingProxyType
def frozendict(*args, **kwargs):
return MappingProxyType(dict(*args, **kwargs))
当然MappingProxyType
不是可以清除的,但是就像the PEP suggested for frozendict
一样,在确保其所有值都是可清除的之后可以使它成为可哈希的(MappingProxyType不能被子类化,因此需要组合并转发方法)。
答案 0 :(得分:6)
MappingProxyType
是映射(例如dict)对象的只读代理。
frozendict
是一个不可变的词典
代理模式是(引用wikipedia):
代理,最常见的形式,是一个充当的类 接触其他东西。
MappingProxyType
只是一个访问真实对象的简单代理(即界面)(真实地图,在我们的例子中是dict)。
建议的frozendict
对象与冻结集一样。只读(不可变)对象,只能在创建时更改。
那么为什么我们需要MappingProxyType
?示例用例是您希望将字典传递给另一个函数但不能更改字典的情况,它充当只读代理,(引用python docs):
映射的只读代理。它提供了动态视图 映射的条目,表示映射更改时的视图 反映了这些变化。
让我们看一下MappingProxyType
In [1]: from types import MappingProxyType
In [2]: d = {'a': 1, 'b': 2}
In [3]: m = MappingProxyType(d)
In [4]: m['a']
Out[4]: 1
In [5]: m['a'] = 5
TypeError: 'mappingproxy' object does not support item assignment
In [6]: d['a'] = 42
In [7]: m['a']
Out[7]: 42
In [8]: for i in m.items():
...: print(i)
('a', 42)
('b', 2)
因为PEP没有进入python,我们无法确定实现的是什么。 通过观察PEP我们看到:
frozendict({'a': {'b': 1}})
会引发异常,因为{'b': 1}
不是可散列的值,但在您的实现中它将创建对象。当然,您可以按照PEP中的说明添加值的验证。
我假设PEP的一部分是内存优化,并且这种冻结的实现可以从使用__hash__
实现的dict比较的性能中受益。
答案 1 :(得分:0)
我注意到的一件事是frozendict.copy
支持添加/替换(限于字符串键),而MappingProxyType.copy
不支持。例如:
d = {'a': 1, 'b': 2}
from frozendict import frozendict
fd = frozendict(d)
fd2 = fd.copy(b=3, c=5)
from types import MappingProxyType
mp = MappingProxyType(d)
# mp2 = mp.copy(b=3, c=5) => TypeError: copy() takes no keyword arguments
# to do that w/ MappingProxyType we need more biolerplate
temp = dict(mp)
temp.update(b=3, c=5)
mp2 = MappingProxyType(temp)
注意:这两个不可变映射都不支持“删除并返回新的不可变副本”操作。
答案 2 :(得分:0)
MappingProxyType仅在第一级上添加不变性:
>>> from types import MappingProxyType
>>> d = {'a': {'b': 1}}
>>> md = MappingProxyType(d)
>>> md
mappingproxy({'a': {'b': 1}})
>>> md['a']['b']
1
>>> md['a']['b'] = 3
>>> md['a']['b']
3
答案 3 :(得分:0)
MappingProxyType
也非常慢。我建议你使用 frozendict
PS:我是包裹的新主人