我有一个充满关键对象对的字典。我想使字典不可变,我认为最好/最简单的方法是将它转换为冻结集,但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的函数)
有没有更好的方法使字典不可变或如何根据密钥检索对象?
编辑:
我最终使用tuple(obfuscator.items())
将dict转换为元组
然后写了我自己的查找值函数:
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
我要感谢大家的努力和投入。
答案 0 :(得分: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]
会奏效。
答案 1 :(得分:0)
你可以创建一个包含字典的包装类,它有一个get item函数但没有set item。您可能需要为线程安全和散列添加一些内容,但基本类不会太困难。
答案 2 :(得分:0)
我能想到达到你想要的最简单方法是继承标准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就像标准字典一样打印出来:
{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})
例如,会更新它,但这个解决方案可能还不错 - 它取决于更广泛的要求。
答案 3 :(得分:0)
既然你在原帖中提到了tuple(dict)
,那么实现你想要的最简单的解决办法可能就是:
tuple(dict.items())
答案 4 :(得分: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()
完全相同。然后就冻结了。