运行此代码时,结果会按预期更改,因为集合是无序的:
my_set_1 = {'a','b','c',}
print([i for i in my_set_1])
也就是说,多次运行会给出不同的列表,例如
['a', 'c', 'b']
['b', 'a', 'c']
['a', 'c', 'b']
['c', 'b', 'a']
等
(注意:如果您没有PYTHONHASHSEED=random
,则可能会获得相同的结果,如评论中所建议的那样。另外,如果您使用控制台进行复制它,确保每次运行代码时
然而,当将上述代码放在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']
# ....
for循环的单次运行将打印相同的列表。重新运行for循环可以打印不同的列表(例如['c', 'b', 'a']
),但仍然可以打印10次而不更改。
为什么不改变?
答案 0 :(得分:5)
@ReblochonMasque有一个正确的观点:set基于哈希表,如果运行之间计算的哈希值相同,则运行之间的顺序相同。但是,这种行为容易受到attacks的攻击。
为了防止这些攻击,引入了特殊变量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']
如果你看object.__hash__()
。底部有一个注释(完全与您的情况有关):
注意默认情况下,
__hash__()
,str
和bytes
个对象的datetime
值为" salted"具有不可预测的随机值。尽管它们在单个Python进程中保持不变,但在重复调用Python之间无法预测它们。
答案 1 :(得分:4)
你不应该期望一组的顺序会改变;集合在某种意义上是无序的,即订单不是不变的i / e,不能保证它不会改变。
实现是以哈希表(字典)的形式;只要没有钥匙碰撞,订单可能不会改变,但没有说明。也无法预测是否或何时会发生这种情况。
从您的实验中得出结论时要小心:您得到的结果无法预测,并且取决于您运行时系统的状态。他们也不会跨越平台,python等版本......