我不明白如何通过'任意'顺序完成字典或python中的循环.
我的意思是,它是一种编程语言,所以语言中的所有内容都必须100%确定,对吗?Python必须有某种算法来决定选择字典或集合的哪一部分,第一,第二等等.
我错过了什么?
出于缓存目的,我需要从dict中存在的GET参数生成缓存键.
目前我正在使用sha1(repr(sorted(my_dict.items())))(sha1()是一种在内部使用hashlib的便捷方法),但我很好奇是否有更好的方法.
Windows XP,Python 2.5:
hash('http://stackoverflow.com') Result: 1934711907
Run Code Online (Sandbox Code Playgroud)
Google App Engine(http://shell.appspot.com/):
hash('http://stackoverflow.com') Result: -5768830964305142685
Run Code Online (Sandbox Code Playgroud)
这是为什么?我怎样才能有一个哈希函数,它可以在不同平台(Windows,Linux,Mac)上提供相同的结果?
我需要能够存储numpy array一个dict用于缓存的目的.哈希速度很重要.
该array代表indicies,所以在对象的真实身份并不重要,值.可变性不是一个问题,因为我只对当前价值感兴趣.
我应该散列什么才能将其存储在一个dict?
我目前的方法是使用str(arr.data),这比md5我的测试更快.
我已经从答案中加入了一些例子来了解相对时间:
In [121]: %timeit hash(str(y))
10000 loops, best of 3: 68.7 us per loop
In [122]: %timeit hash(y.tostring())
1000000 loops, best of 3: 383 ns per loop
In [123]: %timeit hash(str(y.data))
1000000 loops, best of 3: 543 ns per loop
In [124]: %timeit y.flags.writeable = False ; hash(y.data)
1000000 loops, best of 3: 1.15 us per loop
In [125]: %timeit hash((b*y).sum())
100000 loops, …Run Code Online (Sandbox Code Playgroud) 在python中,我试图找到最快的方法来散列pandas数据框中的每个值.
我知道任何字符串都可以使用:
hash('a string')
Run Code Online (Sandbox Code Playgroud)
但是如何在pandas数据框的每个元素上应用此函数?
这可能是一件非常简单的事情,但我刚刚开始使用python.
在我的程序中,我需要存储与许多(我们谈论数十万、数百万)游戏板状态相关的数据。为此,我使用字典。
class BoardState(object):
def __init__(self, ...):
# ...
self.board = [ [ None ] * self.cols for _ in xrange(self.rows) ]
def __hash__(self):
board_tuple = tuple([ tuple(row) for row in self.board ])
return hash(board_tuple)
# ...
Run Code Online (Sandbox Code Playgroud)
self.board在我的主要用例中,是一个 2D 列表,有 6 行和 7 列。
一开始我dict用BoardState对象索引了。但由于除了将来的查找之外,我不会将BoardState存储的对象dict用于其他目的,因此我注意到我可以通过索引来节省内存hash(board_state)(此版本使用的内存减少了 4 倍)。
BoardState两个不同的对象(内部有不同的boards)在 ing 后产生相同值的可能性有多大hash?
为了澄清一点,这就是我存储和检索值的方式dict:
board_state = BoardState(...)
my_values[hash(board_state)] = { ... }
...
other_val_with_board_state = source_function() …Run Code Online (Sandbox Code Playgroud) 多次运行此代码
t = {'a', 'b', 'c', 'd'}
print(t)
Run Code Online (Sandbox Code Playgroud)
可以打印像:
{'c', 'b', 'a', 'd'}
{'d', 'b', 'c', 'a'} # different
{'d', 'b', 'c', 'a'} # same
{'a', 'd', 'b', 'c'} # different
{'a', 'b', 'c', 'd'} # different
# etc
Run Code Online (Sandbox Code Playgroud)
(如果您使用控制台进行复制,请确保在Rerun每次重新粘贴代码并执行之前单击.如果仍然无法复制,可能您的散列随机化不等于random.在Python 3.3及更高版本上,默认情况下启用哈希随机化.)
另一方面,下面的代码总是打印相同的集合,它实际上是排序的:
s = {1, 6, 3.3, 4}
print(s)
# prints:
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}
# {1, 3.3, 4, 6}
Run Code Online (Sandbox Code Playgroud)
问题: …
正如许多人所指出的,Python 的hash不再一致(从版本 3.3 开始),因为PYTHONHASHSEED现在默认使用随机(为了解决安全问题,如这个优秀答案中所解释的)。
但是,我注意到某些对象的哈希值仍然是一致的(无论如何,从 Python 3.7 开始):包括int, float, tuple(x), frozenset(x)(只要x产生一致的哈希值)。例如:
assert hash(10) == 10
assert hash((10, 11)) == 3713074054246420356
assert hash(frozenset([(0, 1, 2), 3, (4, 5, 6)])) == -8046488914261726427
Run Code Online (Sandbox Code Playgroud)
这总是正确且有保证的吗?如果是这样,预计这种情况会持续下去吗?是PYTHONHASHSEED唯一适用于字符串和字节数组的哈希值加盐吗?
我为什么要问?
我有一个依赖哈希来记住我们是否已经看到给定字典(以任何顺序)的系统:{key: tuple(ints)}。在该系统中,键是文件名的集合,元组是 的子集os.stat_result,例如(size, mtime)与它们相关联。该系统用于根据检测差异做出更新/同步决策。
在我的应用程序中,我有大约 100K 个这样的字典,每个字典可以代表数千个文件及其状态,因此缓存的紧凑性很重要。
我可以容忍来自可能的哈希冲突的小误报率(对于 64 位哈希,< 10^-19)(另请参阅生日悖论)。
对于每个这样的字典“”,一个紧凑的表示如下fsd:
def fsd_hash(fsd: dict):
return hash(frozenset(fsd.items()))
Run Code Online (Sandbox Code Playgroud)
它非常快,并产生一个 int 来表示整个字典(具有顺序不变性)。如果fsd字典中的任何内容发生变化,则哈希值很可能会有所不同。
不幸的是, …
运行此代码时,结果会按预期更改,因为集合是无序的:
my_set_1 = {'a','b','c',}
print([i for i in my_set_1])
Run Code Online (Sandbox Code Playgroud)
也就是说,多次运行会给出不同的列表,例如
['a', 'c', 'b']
['b', 'a', 'c']
['a', 'c', 'b']
['c', 'b', 'a']
Run Code Online (Sandbox Code Playgroud)
等等
(注意:您可能会获得相同的结果,如果您没有PYTHONHASHSEED=random,请按照注释中的建议.另外,如果您使用控制台进行复制,请确保Rerun每次运行代码时都使用控制台.)
但是,将上面的代码放在for循环中时,结果相当令人惊讶:
for i in range(10):
my_set_1 = {'a','b','c',}
print([i for i in my_set_1])
# Prints:
# ['a', 'c', 'b']
# ['a', 'c', 'b']
# ['a', 'c', 'b']
# ....
Run Code Online (Sandbox Code Playgroud)
for循环的单次运行将打印相同的列表.重新运行for循环可以打印不同的列表(例如['c', 'b', 'a']),但仍然可以打印10次而不更改.
为什么不改变?
python ×9
hash ×5
set ×3
dictionary ×2
for-loop ×1
numpy ×1
pandas ×1
python-2.7 ×1
python-3.4 ×1
python-3.x ×1
unordered ×1