几个月前,我使用了这个实现:Python可哈希字典。
然而,我的一位同事告诉我:“它并不是真正的不可变,因此不安全。你可以使用它,但这让我感觉像只悲伤的熊猫。”
所以我开始寻找创建一个真正不可变的字典。我不需要将“键-字典”与另一个“键-字典”进行比较。它仅用作另一个字典的键。
我想到了以下代码:
class HashableDict(dict):
"""Hashable dict that can be used as a key in other dictionaries"""
def __new__(self, *args, **kwargs):
# create a new local dict, that will be used by the HashableDictBase closure class
immutableDict = dict(*args, **kwargs)
class HashableDictBase(object):
"""Hashable dict that can be used as a key in other dictionaries. This is now immutable"""
def __key(self):
"""Return a tuple of the current keys"""
return tuple((k, immutableDict[k]) for k in sorted(immutableDict))
def __hash__(self):
"""Return a hash of __key"""
return hash(self.__key())
def __eq__(self, other):
"""Compare two __keys"""
return self.__key() == other.__key() # pylint: disable-msg=W0212
def __repr__(self):
"""@see: dict.__repr__"""
return immutableDict.__repr__()
def __str__(self):
"""@see: dict.__str__"""
return immutableDict.__str__()
def __setattr__(self, *args):
raise TypeError("can't modify immutable instance")
__delattr__ = __setattr__
return HashableDictBase()
我使用以下内容来测试功能:
d = {"a" : 1}
a = HashableDict(d)
b = HashableDict({"b" : 2})
print a
d["b"] = 2
print a
c = HashableDict({"a" : 1})
test = {a : "value with a dict as key (key a)",
b : "value with a dict as key (key b)"}
print test[a]
print test[b]
print test[c]
它的输出结果如下:
{'a': 1}
{'a': 1}
带有字典作为键的值(键是a)
带有字典作为键的值(键是b)
带有字典作为键的值(键是a)
这是我可以使用的最佳不可变字典,以满足我的要求吗?如果不是,有更好的解决方案吗?
tuple(sorted(immutableDict.items()))
(在Python 3.x之前使用iteritems()
)。 另外,只是提一下,由于 Python 中已经有了frozenset
类,为了保持命名一致性,我会选择FrozenDict
作为名称 - 尽管这并不重要。 - Gareth Latty