Python 3中的不可变字典:如何使keys(),items()和values()字典视图不可变

Immutable dictionary in Python 3: how to make keys(), items(), and values() dictionary views immutable

简短的版本:什么是最好的方法来覆盖dict.keys()和朋友,以防止自己在python 3中意外地修改(假定是)不可变的字典?

在最近的一个问题中,我问了关于用Python散列不可变字典的问题。从那时起,我已经建立了一个我喜欢的不变的,可散列的字典。然而,我意识到它有一个漏洞:keys()items()values()返回的字典视图仍然允许我自己意外地改变我的(假定)不变的字典。

关于栈溢出,我能找到的关于字典视图的唯一问题是python创建自己的字典子集的dict视图,但是这似乎与我的问题没有太多关系,对于"冻结的dict"是什么的答案呢?似乎没有凌驾于keys()等之上。

这样做是否可以防止我意外地修改(例如)不可变字典的键?

1
2
3
4
5
6
7
8
9
class FrozenCounter(collections.Counter):
   "Model an hashable multiset as an immutable dictionary."
    # ...
    def keys(self):
        return list(super().keys())
    def values(self):
        return list(super().values())
    def items(self):
        return list(super().items())


我从答案中收集到的信息

我主要不识字。

dictview无法修改dict。在python 3文档中,我误读了,"它们提供了字典条目的动态视图,这意味着当字典更改时,视图会反映这些更改",意思是"当视图更改时,字典会反映这些更改。"显然,这不是文档所说的。


在python 2.x中,视图不允许改变底层对象:

1
2
3
4
5
6
7
>>> a = { 'a' : 1 }
>>> a.keys()[0] = 'b'
>>> a
{'a': 1}
>>> a.values()[0] = 'b'
>>> a
{'a': 1}

在python 3.x中,可变视图会产生一个类型错误:

1
2
3
4
5
>>> a = { 'a':1}
>>> a.keys()[0] = 'b'
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
TypeError: 'dict_keys' object does not support item assignment


这可能是一个坏主意,因为它打破了那些方法首先返回视图的假设,并用不再更新以匹配基础dict的可变对象替换它们。

你的观点是如何改变你的字典的?视图不支持项分配或删除,因此我不相信它们可以更改基础字典。