Fer*_*dox 2 python for-loop set unordered python-3.x
运行此代码时,结果会按预期更改,因为集合是无序的:
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次而不更改.
为什么不改变?
@ReblochonMasque有一个正确的观点:set基于哈希表,如果运行之间计算的哈希值相同,则运行之间的顺序相同.但是这种行为很容易受到攻击.
为了防止这些攻击PYTHONHASHSEED,引入了特殊变量.当它设置为random每次运行时,Python将为相同的项生成不同的哈希值.这就是为什么你得到不同的订单.
要检查这一点,您可以使用PYTHONHASHSEED设置为相同的数字来运行程序.在运行中订单将是相同的.
$ export PYTHONHASHSEED=random
$ python t.py
['a', 'b', 'c']
$ python t.py
['a', 'c', 'b']
$ python t.py
['c', 'b', 'a']
$ export PYTHONHASHSEED=4
$ python t.py
['a', 'b', 'c']
$ python t.py
['a', 'b', 'c']
$ python t.py
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)
如果你看看object.__hash__().底部有一个注释(完全与您的情况有关):
注意:默认情况下,该
__hash__()值str,bytes并且datetime对象是"咸"不可预测的随机值.虽然它们在单个Python进程中保持不变,但是在重复调用Python之间它们是不可预测的.
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |