Python 缺少 frozen-dict 类型的解决方法?
A workaround for Python's missing frozen-dict type?
在Python中,当你想使用列表作为某些字典的键时,你可以将它们变成元组,元组是不可变的,因此是可散列的。
>>> a = {}
>>> a[tuple(list_1)] = some_value
>>> a[tuple(list_2)] = some_other_value
当你想使用 set 对象作为某些字典的键时,同样的情况会发生——你可以构建一个 frozenset,这又是不可变的,因此是可散列的。
>>> a = {}
>>> a[frozenset(set_1)] = some_value
>>> a[frozenset(set_2)] = some_other_value
但是字典似乎没有对应的东西。
我想到的第一个想法(最后发现它很糟糕)是使用 str(some_dict)
作为密钥。但是,字典总是使用不同的散列函数(这会影响元素的顺序),所以相同字典的字符串可能不同。
是否有任何被称为良好做法的解决方法,或者是否有人对如何使用类似字典的对象作为其他字典的键有其他想法?
您可以尝试 ordered dict 或查看这些答案:
- What would a "frozen dict" be?
- Immutable dictionary, only use as a key for another dictionary
- How to create an immutable dictionary in python?
PyPI 上什至还有一个包:https://pypi.python.org/pypi/frozendict
您也可以简单地将字典转换为元组(sorted(your_dict.items())
),然后用作散列。
UPD:如评论中所述,OrderedDict 不可散列。我的错,它真的不应该是可散列的,因为它是可变的。
编辑:
从Python 3.6 开始,字典保留插入顺序。因此,解决方法会因使用的 Python 版本而异。
对于Python < 3.6(字典不保留插入顺序) - 使用frozenset,这样两个集合是即使顺序不同也相等:
>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = frozenset(a.items())
>>> frozenset_restored_to_dict = dict(b)
>>> frozenset_restored_to_dict
{'key2': 'val2', 'key1': 'val1'}
否则(字典保留插入顺序),使用元组。这样,可以在保留项目顺序的同时恢复字典,但是,具有不同排序的相同项目的元组将不相等。解决方法是每次在进行比较之前将元组传递给 frozenset 构造函数。
>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = tuple(a.items())
>>> tuple_restored_to_dict = dict(b)
>>> tuple_restored_to_dict
{'key1': 'val1', 'key2': 'val2'}
从代码中可以看出,b
是一个元组,也就是frozenset。两者都是不可变的和可散列的,并且可以完全恢复为像 a
.
这样的常规字典
在Python中,当你想使用列表作为某些字典的键时,你可以将它们变成元组,元组是不可变的,因此是可散列的。
>>> a = {}
>>> a[tuple(list_1)] = some_value
>>> a[tuple(list_2)] = some_other_value
当你想使用 set 对象作为某些字典的键时,同样的情况会发生——你可以构建一个 frozenset,这又是不可变的,因此是可散列的。
>>> a = {}
>>> a[frozenset(set_1)] = some_value
>>> a[frozenset(set_2)] = some_other_value
但是字典似乎没有对应的东西。
我想到的第一个想法(最后发现它很糟糕)是使用 str(some_dict)
作为密钥。但是,字典总是使用不同的散列函数(这会影响元素的顺序),所以相同字典的字符串可能不同。
是否有任何被称为良好做法的解决方法,或者是否有人对如何使用类似字典的对象作为其他字典的键有其他想法?
您可以尝试 ordered dict 或查看这些答案:
- What would a "frozen dict" be?
- Immutable dictionary, only use as a key for another dictionary
- How to create an immutable dictionary in python?
PyPI 上什至还有一个包:https://pypi.python.org/pypi/frozendict
您也可以简单地将字典转换为元组(sorted(your_dict.items())
),然后用作散列。
UPD:如评论中所述,OrderedDict 不可散列。我的错,它真的不应该是可散列的,因为它是可变的。
编辑:
从Python 3.6 开始,字典保留插入顺序。因此,解决方法会因使用的 Python 版本而异。
对于Python < 3.6(字典不保留插入顺序) - 使用frozenset,这样两个集合是即使顺序不同也相等:
>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = frozenset(a.items())
>>> frozenset_restored_to_dict = dict(b)
>>> frozenset_restored_to_dict
{'key2': 'val2', 'key1': 'val1'}
否则(字典保留插入顺序),使用元组。这样,可以在保留项目顺序的同时恢复字典,但是,具有不同排序的相同项目的元组将不相等。解决方法是每次在进行比较之前将元组传递给 frozenset 构造函数。
>>> a = {'key1' : 'val1', 'key2' : 'val2'}
>>> b = tuple(a.items())
>>> tuple_restored_to_dict = dict(b)
>>> tuple_restored_to_dict
{'key1': 'val1', 'key2': 'val2'}
从代码中可以看出,b
是一个元组,也就是frozenset。两者都是不可变的和可散列的,并且可以完全恢复为像 a
.