heapq.nlargest 产生不一致的结果

heapq.nlargest produces inconsistent results

以下代码多次执行会产生不一致的结果。我 运行 在 Debian 8.4 (jessie) 上 Python-3.5.1.

from heapq import nlargest
from operator import itemgetter

dd = dict([('41', 768.0), ('2', 15275.0), ('9', 1728.0), ('90', 1728.0),
           ('97', 1200.0), ('68', 2904.0), ('98', 4380.0), ('16', 768.0),
           ('37', 768.0), ('17', 1587.0), ('25', 4495.4)])

print(nlargest(5, dd.items(), key=itemgetter(1)))

多次执行后的输出:

[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('90', 1728.0)]
[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('9', 1728.0)]
[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('90', 1728.0)]
[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('90', 1728.0)]

看起来 运行dom,谁能解释为什么会这样?

如果将 dd.items() 替换为 sorted(dd.items()),则输出将变得确定。即

[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('9', 1728.0)]

我也在 OSX 和 CentOS6.7 上用 python-2.7 试过上面的代码,它总是 returns

[('2', 15275.0), ('25', 4495.4), ('98', 4380.0), ('68', 2904.0), ('9', 1728.0)]

这可能是 Python3 heapq 实现中的错误吗?

您要求的是最大的 5 件商品,并列第 5 名。 Python 如何打破平局是任意的,所涉及的任何不确定行为都不是错误。

它不确定的原因是字典迭代顺序是任意的,并且自 Python 3.3 以来,字符串和某些其他类型的哈希随机化已默认启用。因此,heapq.nlargest 接收 dict 项目的顺序有一个随机组成部分,它打破关系的方式取决于它看到项目的顺序。