我想它可能是类似的collections.namedtuple,但这更像是一个冻结的词典(一个半冻结的词典).不是吗?
A"frozendict"应该是一个冰冻的字典,它应该有keys,values,get,等,并支持in,for等等.
简短版本:作为无序项目字典实现的多集合的最佳散列算法是什么?
我正在尝试将一个不可变的multiset(这是一个包或其他语言的多重集合:像一个数学集,除了它可以容纳多个元素)作为字典实现.我已经创建了标准库类的子类collections.Counter,类似于这里的建议:Python hashable dicts,它建议像这样的哈希函数:
class FrozenCounter(collections.Counter):
# ...
def __hash__(self):
return hash(tuple(sorted(self.items())))
Run Code Online (Sandbox Code Playgroud)
创建完整的项目元组会占用大量内存(相对于使用生成器而言),并且哈希将在我的应用程序的内存密集型部分中发生.更重要的是,我的字典键(multiset元素)可能不会是可订购的.
我正在考虑使用这个算法:
def __hash__(self):
return functools.reduce(lambda a, b: a ^ b, self.items(), 0)
Run Code Online (Sandbox Code Playgroud)
我想使用按位XOR意味着顺序与散列值无关,与元组的散列不同?我想我可以在我的数据的无序流序列上半实现Python元组散列算法.请参阅https://github.com/jonashaag/cpython/blob/master/Include/tupleobject.h(在页面中搜索"hash"一词) - 但我几乎不知道有足够的C来阅读它.
思考?建议?谢谢.
set(),但事情必须是哈希的.)
@marcin和@senderle都给出了相同的答案:使用hash(frozenset(self.items())).这是有道理的,因为items()"视图"是设置的.@marcin是第一个,但我给@senderle打了一个复选标记,因为对不同解决方案的大O运行时间进行了很好的研究.@marcin还提醒我要包含一个__eq__方法 - 但是继承自的方法dict会很好用.这就是我实现所有内容的方式 - 欢迎基于此代码的进一步意见和建议:
class FrozenCounter(collections.Counter):
# Edit: A previous version of this code included a __slots__ definition.
# But, from the Python documentation: "When …Run Code Online (Sandbox Code Playgroud) 在Python中,当你想使用列表作为某些字典的键时,你可以把它们变成元组,这些元组是不可变的,因此是可以删除的.
>>> a = {}
>>> a[tuple(list_1)] = some_value
>>> a[tuple(list_2)] = some_other_value
Run Code Online (Sandbox Code Playgroud)
当您想要将set对象用作某些字典的键时,也会发生同样的情况- 您可以构建一个冷冻集,这也是不可变的,因此是可清除的.
>>> a = {}
>>> a[frozenset(set_1)] = some_value
>>> a[frozenset(set_2)] = some_other_value
Run Code Online (Sandbox Code Playgroud)
但似乎对于字典没有等价物.
我想到的第一个想法(最终发现它很糟糕)是str(some_dict)用作关键.但是,字典总是使用不同的散列函数,因此相同字典的字符串可能不同.
是否有任何解决方法称为良好实践,或者是否有人有其他想法如何使用类字典对象作为其他词典的键?
由于这里关于这个主题的许多问题证明了这一点,所以拿一本字典是一个非常常见的任务,有一个相当不错的解决方案:
{k:v for k,v in dict.viewitems() if some_test(k,v)}
Run Code Online (Sandbox Code Playgroud)
但是这会创建一个新的字典,并带有自己的映射.对于许多操作,只有原始字典的不可变视图(即它不支持视图上的赋值或删除操作)会很好.实现这样的类型可能很容易,但是增加本地实用程序类并不好.
所以,我的问题是:是否有内置的方式来获得这样的"子集视图"?或者是否有第三方库(最好通过PyPi提供)提供这种实用程序的良好实现?