Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 具有键对象对的不可变字典_Python_Python 2.7_Dictionary_Frozenset - Fatal编程技术网

Python 具有键对象对的不可变字典

Python 具有键对象对的不可变字典,python,python-2.7,dictionary,frozenset,Python,Python 2.7,Dictionary,Frozenset,我有一本充满关键对象对的字典。我想使字典不可变,我认为最好/最简单的方法是将其强制转换为冻结集,但冻结集(dict)和元组(dict)只存储键 使用frozenset(dict.items())我似乎得到了一个带有键对象对的frozenset,但我不知道如何检索值/键 我有以下代码,只要“\uuuufuscators”是一个字典,它就可以工作 def obfuscate_value(self, key, value): obfuscator = self.__obfuscators.ge

我有一本充满关键对象对的字典。我想使字典不可变,我认为最好/最简单的方法是将其强制转换为冻结集,但
冻结集(dict)
元组(dict)
只存储键

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

我有以下代码,只要“\uuuufuscators”是一个字典,它就可以工作

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没有\\uu getitem \
self.\uuuuu模糊器。\uuuuu getattribute\uuuuuu(key)
总是说它没有该属性(因为我假设它搜索名为key的函数) 有没有更好的方法使字典不可变,或者如何根据键检索对象

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

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

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

您可以创建一个包装器类,该类使用字典并具有get item函数,但没有set item。您可能需要为线程安全和哈希添加一些东西,但基本类不会太难。

我能想到的实现您想要的功能的最简单方法是对标准
dict
类型进行子类化,并覆盖其
\u setitem\u
方法:

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}
但当您尝试更改值(或添加新值)时:


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

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


将起作用。

既然您在原始帖子中提到了
tuple(dict)
,那么实现您想要的可能最简单的解决方案就是:

tuple(dict.items())

您需要一个能够冻结的
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

在您调用
.freeze()
之前,它的行为将与通常的
dict
完全相同。然后它被冻结。

如何子类化
collections.Mapping
或使用
Mappingproxy
。据我所知,两者都是不可变的(对于给定的不可变值)。这是否回答了你的问题?我确实考虑过这个问题,但我希望有一个比创建自己的自定义字典类更简单/更快的解决方案。特别是因为我现在看起来很接近,因为我有一个带有键对象对的冻结集,但我无法访问它们,或者至少我不知道如何使用此选项,我仍然面临与
冻结集(dict.items())
相同的问题。如何根据键访问值?当再次考虑此选项时,我意识到如果我创建自己的搜索功能,那么它可能是更容易的解决方案,因为所有其他选项都不简单
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
d = { 'a': [1] }
fd = MappingProxyType(d)
fd['a'].append(2)
fd['a']
#output:
[1,2]
tuple(dict.items())
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