为什么有时会保持既定秩序?
Why is set order maintained sometimes?
当运行使用此代码时,结果会按预期更改,因为集合是无序的:
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
,您可能会得到相同的结果,如评论中所建议的那样。另外,如果您是使用控制台复制它,确保每次 运行 代码时 Re运行 控制台。)
然而,当将上述代码放在 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 次而不会改变。
为什么没有改变?
你不要指望集合的顺序会改变;从某种意义上说,集合是无序的,因为顺序不是不变的 i/e 不能保证它不会改变。
以hash的形式实现table(字典);只要没有按键冲突,顺序就可能不会改变,但没有人知道。也无法预测是否会发生或何时发生。
从您的实验中得出结论时要小心:您得到的结果无法预测,将取决于您 运行 时系统的状态。它们也不会跨平台、python 版本等...
@ReblochonMasque 有一个正确的观点:set 基于散列 table,如果 运行 之间计算的散列相同,则 运行 之间的顺序相同]s。然而,这种行为很容易受到 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__()
。底部有一条注释(正是关于您的情况):
Note By default, the __hash__()
values of str
, bytes
and datetime
objects are "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.
当运行使用此代码时,结果会按预期更改,因为集合是无序的:
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
,您可能会得到相同的结果,如评论中所建议的那样。另外,如果您是使用控制台复制它,确保每次 运行 代码时 Re运行 控制台。)
然而,当将上述代码放在 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 次而不会改变。
为什么没有改变?
你不要指望集合的顺序会改变;从某种意义上说,集合是无序的,因为顺序不是不变的 i/e 不能保证它不会改变。
以hash的形式实现table(字典);只要没有按键冲突,顺序就可能不会改变,但没有人知道。也无法预测是否会发生或何时发生。
从您的实验中得出结论时要小心:您得到的结果无法预测,将取决于您 运行 时系统的状态。它们也不会跨平台、python 版本等...
@ReblochonMasque 有一个正确的观点:set 基于散列 table,如果 运行 之间计算的散列相同,则 运行 之间的顺序相同]s。然而,这种行为很容易受到 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__()
。底部有一条注释(正是关于您的情况):
Note By default, the
__hash__()
values ofstr
,bytes
anddatetime
objects are "salted" with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.