MappingProxyType和PEP 416 frozendi之间的差异

2024-10-03 15:30:25 发布

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

frozendictwas rejected时,一个相关的类types.MappingProxyType被添加到python3.3中的公共API中。在

我知道MappingProxyType只是底层{}的包装,但是尽管如此,它在功能上不是等价于{}?在

换言之,最初的PEP 416frozendict与此有什么实质性区别:

from types import MappingProxyType
def frozendict(*args, **kwargs):
  return MappingProxyType(dict(*args, **kwargs))

当然,MappingProxyType不是按原样可散列的,但与the PEP suggested for ^{}一样,在确保其所有值都是散列值之后,可以使其成为散列的(MappingProxyType不能子类化,因此需要组合和转发方法)。在


Tags: fromimport功能apiargskwargspeptypes
3条回答

我注意到,frozendict.copy支持add/replace(仅限于字符串键),而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)

注意:这两个不可变映射都不支持“remove and return new immutable copy”操作。在

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

TL;DR

MappingProxyType是映射(例如dict)对象的只读代理。在

frozendict是一个不可变的dict

回答

代理模式是(引用wikipedia):

A proxy, in its most general form, is a class functioning as an interface to something else.

MappingProxyType只是一个简单的代理(即接口)来访问真实对象(在我们的示例中是dict的真实映射)。在

建议的frozendict对象就像set是frozenset一样。只读(不可变)对象,只能在创建时更改。在

那么为什么我们需要MappingProxyType?示例用例是您希望将字典传递给另一个函数,但它不能更改您的字典,它充当一个只读代理(引用python docs):

Read-only proxy of a mapping. It provides a dynamic view on the mapping’s entries, which means that when the mapping changes, the view reflects these changes.

让我们看看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,所以我们无法确定它将是什么实现。 通过查看政治公众人物,我们可以看到:

^{pr2}$

将引发异常,因为{'b': 1}不是散列值,但在您的实现中,它将创建对象。当然,您可以添加PEP中所述的值的验证。在

我假设PEP的一部分是内存优化,这种frozendict的实现可以从使用__hash__实现的dict比较性能中获益。在

相关问题 更多 >