3

我有一个充满键对象对的字典。我想让字典不可变,我认为最好/最简单的方法是将它转换为frozenset,但frozenset(dict)tuple(dict)只存储键。

使用frozenset(dict.items())我似乎得到了一个带有键-对象对的冻结集,但我不知道如何检索值/键。

只要“__obfuscators”是字典,我就有以下代码有效

def obfuscate_value(self, key, value):
    obfuscator = self.__obfuscators.get(key)
    if obfuscator is not None:
        return obfuscator.obfuscate_value(value)
    else:
        return value

我尝试了这个,试图让它与冻结集一起工作:

def obfuscate_value(self, key, value):
    try:
        obfuscator = self.__obfuscators[key]
    except:
        return value
    return obfuscator.obfuscate_value(value)

但这给出了它frozenset does not have \__getitem__ 并且self.__obfuscators.__getattribute__(key)总是说它没有属性(因为我假设这会搜索一个名为 key 的函数)是否有更好的方法使字典不可变或者如何根据键检索对象?

编辑:我最终将dict转换为一个元组tuple(obfuscator.items()) ,然后编写了我自己的查找值函数:

def find_obfuscator(self, key):
    for item in self.__obfuscators:
        x, y = item
        if self.case_insensitive:
            if x.lower() == key.lower():
                return y
        else:
            if x == key:
                return y

我要感谢大家的努力和投入。

4

5 回答 5

2

您可以使用以下方法创建字典的不可变视图types.MappingProxyType

from types import MappingProxyType
d = { 'a': 1 }
fd = MappingProxyType(d)
fd['a']
#output:
1

fd['a'] = 2
#output:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment

请注意,您仍然可以更改 vaule 对象,因此:

d = { 'a': [1] }
fd = MappingProxyType(d)
fd['a'].append(2)
fd['a']
#output:
[1,2]

将工作。

于 2016-08-04T14:54:16.293 回答
1

我能想到的实现你想要的最简单的方法是继承标准dict类型并覆盖它的__setitem__方法:

class MyDict(dict):
    def __setitem__(self, key, value):
        raise NotImplementedError("This is a frozen dictionary")

这允许您创建以后无法通过项目分配更改的字典:

d = MyDict({1: 2, 3: 4})

或者,等效地:

d = MyDict([(1, 2), (3, 4)])

然后 dict 像标准 dict 一样打印出来:

{1: 2, 3: 4}

但是当您尝试更改一个值(或添加一个新值)时:

d[1] = 15
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-21-a22420992053> in <module>()
----> 1 d[1] = 34

<ipython-input-18-03f266502231> in __setitem__(self, key, value)
      1 class MyDict(dict):
      2     def __setitem__(self, key, value):
----> 3         raise NotImplementedError("This is a frozen dictionary")

NotImplementedError: This is a frozen dictionary

请注意,这不是完全不可变的,但是:

d.update({1:17})

例如,将对其进行更新,但此解决方案可能已经足够好 - 它取决于更广泛的要求。

于 2016-08-04T14:47:07.350 回答
0

由于您tuple(dict)在原始帖子中提到,可能实现您想要的最简单的解决方案可能只是:

tuple(dict.items())
于 2016-08-04T15:02:51.790 回答
0

你需要一个dict能够冷冻的吗?您可以简单地制作一个:

class FrozenDict(dict):
    def __init__(self, *args, **kwargs):
        self._frozen = False
        dict.__init__(self, *args, **kwargs)
    def freeze(self):
        self._frozen = True
    def __setitem__(self, key, value):
        if (self._frozen):
            raise TypeError("Attempted assignment to a frozen dict")
        else:
            return dict.__setitem__(self, key, value)

a = FrozenDict({7:8})
a[5] = 6
print(a)
a.freeze()
a[3] = 2 # raises TypeError

dict在您调用.freeze(). 然后它被冻结了。

于 2016-08-04T15:08:29.073 回答
0

您可以制作一个包装类,它接受字典并具有获取项目功能但没有设置项目。您可能需要为线程安全和散列添加一些东西,但基本类不会太难。

于 2016-08-04T14:43:41.093 回答