![](/img/trans.png)
[英]Sorting list of values in the returned dictionary in ascending order-Python
[英]Random order of returned values in python dictionary
我不明白这一点,它会困扰我直到我明白。
此 python 代码计算每个字符出现在 'message' 变量中的次数:
message = 'Some random string of words'
dictionary= {}
for character in message.upper():
dictionary.setdefault(character,0)
dictionary[character] = dictionary[character] + 1
print(dictionary)
如果您多次运行它,您会注意到计数每次都以看似随机的顺序返回。 为什么是这样? 我认为循环应该每次都从字符串的开头开始,并以一致的顺序返回值……但事实并非如此。 在setdefault()
、 print()
或upper()
方法中是否存在一些影响字符串处理顺序的随机元素?
由于两件事:
print(hash(message))
或者甚至只是print(hash('c'))
那么你会看到不同的运行也不同。 因此,由于顺序取决于哈希值,并且哈希值从一次运行变为下一次运行,当然您可以获得不同的顺序。
另一方面,如果你在同一次运行中重复它,你可能会获得相同的顺序:
message = 'Some random string of words'
for _ in range(10):
dictionary= {}
for character in message:
dictionary.setdefault(character,0)
dictionary[character] = dictionary[character] + 1
print(dictionary)
我只是跑了它,它按照预期打印了完全相同的订单十次。 然后我再次运行它,它打印了一个不同的顺序,但再次十次相同。 正如所料。
dict
本质上是无序的。
从Python文档 :
键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史。
编辑
正确实现目标的代码的替代方法是使用OrderedCounter
:
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
message = 'Some random string of words'
print(OrderedCounter(message.upper()))
这是因为安全性而发生的。 当您编写任何外部用户可以提供最终在字典中的数据的应用程序时,您需要确保他们不知道散列的结果是什么。 如果他们这样做,他们可以确保他们提供的每个新条目将散列到同一个bin。 当他们这样做时,你最终得到的是“分摊的O(1)
”检索,而不是O(n)
,因为字典中的每个get()
都会得到相同的bin,并且必须遍历其中的所有项目。 (或者可能更长时间考虑其他处理请求)
有关更多信息, 请查看https://131002.net/siphash/siphashdos_appsec12_slides.pdf 。
几乎所有语言都通过在启动时生成随机数并将其用作散列种子来防止这种情况,而不是从某个预定义的数字(如0
。
实现dict
的方式是为了使查找快速有效。 即使dict
的大小增加。 在引擎盖下,这意味着密钥顺序可能会改变。
如果键的顺序对您很重要,请尝试使用collections
的ordereddict
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.