我最近从Python 2.7切换到Python 3.3,似乎在Python 2中字典键的顺序是任意的,但是是一致的,而在Python
3中,使用例如获得的字典键的顺序vars()
似乎是不确定的。
如果我运行:
class Test(object): pass
parameters = vars(Test)
print(list(parameters.keys()))
在Python 2.7和Python 3.3中,则:
Python 2.7一直给我
['__dict__', '__module__', '__weakref__', '__doc__']
使用Python 3.3,我可以获得任何随机顺序–例如:
['__weakref__', '__module__', '__qualname__', '__doc__', '__dict__']
[‘doc’, ‘dict’, ‘qualname’, ‘module’, ‘weakref’]
[‘dict’, ‘module’, ‘qualname’, ‘weakref’, ‘doc’]
[‘weakref’, ‘doc’, ‘qualname’, ‘dict’, ‘module’]
这种不确定性来自何处?为什么会这样
list({str(i): i for i in range(10)}.keys())
…每次运行之间始终如一
['3', '2', '1', '0', '7', '6', '5', '4', '9', '8']
……?
更新: 在Python
3.6中,dict
有一个新的实现可以保留插入顺序。从Python
3.7开始,保证了这种保留顺序的行为:
dict对象的插入顺序保留性质已声明是Python语言规范的正式组成部分。
这是自2012年以来的安全修复程序的结果,该安全修复程序在Python
3.3中默认启用(向下滚动至“安全改进”)。
从公告中:
散列随机化导致dicts和sets的迭代顺序不可预测,并且在Python运行之间有所不同。Python从未保证字典或集合中键的迭代顺序,建议应用程序不要依赖它。从历史上看,dict的迭代顺序在各个发行版中并没有经常改变,并且在连续的Python执行之间始终保持一致。因此,某些现有应用程序可能依赖于dict或set排序。因此,许多不接受不受信任的输入的Python应用程序都不容易受到此攻击的影响,因此在此处提到的所有稳定的Python版本中,默认情况下都禁用了HASH随机化。
如上所述,最后一个大写的位在Python 3.3中不再适用。
另请参阅:
object.__hash__()
文档(“注意”侧栏)。
如果绝对必要,可以通过将PYTHONHASHSEED
环境变量设置为来禁用受此行为影响的Python版本中的哈希随机化0
。
您的反例:
list({str(i): i for i in range(10)}.keys())
......不 不 ,其实总是给予同样的结果在Python
3.3,虽然不同的排序的数量是有限的,由于哈希冲突的处理方式:
$ for x in {0..999}
> do
> python3.3 -c "print(list({str(i): i for i in range(10)}.keys()))"
> done | sort | uniq -c
61 ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
73 ['1', '0', '3', '2', '5', '4', '7', '6', '9', '8']
62 ['2', '3', '0', '1', '6', '7', '4', '5', '8', '9']
59 ['3', '2', '1', '0', '7', '6', '5', '4', '9', '8']
58 ['4', '5', '6', '7', '0', '1', '2', '3', '8', '9']
55 ['5', '4', '7', '6', '1', '0', '3', '2', '9', '8']
62 ['6', '7', '4', '5', '2', '3', '0', '1', '8', '9']
63 ['7', '6', '5', '4', '3', '2', '1', '0', '9', '8']
60 ['8', '9', '0', '1', '2', '3', '4', '5', '6', '7']
66 ['8', '9', '2', '3', '0', '1', '6', '7', '4', '5']
65 ['8', '9', '4', '5', '6', '7', '0', '1', '2', '3']
53 ['8', '9', '6', '7', '4', '5', '2', '3', '0', '1']
62 ['9', '8', '1', '0', '3', '2', '5', '4', '7', '6']
52 ['9', '8', '3', '2', '1', '0', '7', '6', '5', '4']
73 ['9', '8', '5', '4', '7', '6', '1', '0', '3', '2']
76 ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0']
如该答案开头所述,Python 3.6不再是这种情况:
$ for x in {0..999}
> do
> python3.6 -c "print(list({str(i): i for i in range(10)}.keys()))"
> done | sort | uniq -c
1000 ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
问题 你想创建一个字典,并且在迭代或序列化这个字典的时候能够控制元素的顺序。 解决方案 为了能控制一个字典中元素的顺序,你可以使用 collections 模块中的 OrderedDict 类。 在迭代操作的时候它会保持元素被插入时的顺序,示例如下: from collections import OrderedDict d = OrderedDict() d['foo'] = 1 d['bar
值为ReinsDepositAmount ** ** 我最近在kendo UI网格中存储了一个应用程序日期排序。 在剑道网格中,列名是这样定义的 的传入值-月、日、年格式。1991年8月23日 字段名称为ReinsDepositDate: 在对日期进行排序时,其排序基于第一个值 1994年1/12 2015年1月23日 1992年1月13日 意思是当我提升的时候 1994年1/12 1992年1月
有一个问题,为什么他们要求在字典中使用不可变对象作为键。 当我最近使用字典(显然不是为了哈希表)将Xml节点对象作为键放置时,这个问题实际上进入了我的脑海。然后,我在使用过程中多次更新节点。 那么,“使用不可变键”到底意味着什么呢?
问题内容: 所以我有一个字典,打印时看起来像这样: 我想以我定义的自定义方式对它们进行排序。假设我希望按键排序的方式是。 有人知道如何以预定义/自定义的方式整理字典吗?我正在做的是从数据库中获取此词典,它可以带有20多个键,所有键都有特定的顺序。总是设置顺序,但有时某些键/值不会出现在字典中。所以这也可能发生: (按键排序)为。 因此,在此示例中不存在10,但是我需要的排序仍然相同,仅缺少10。
问题内容: 为什么字典键必须是不可变的?我正在寻找一个简单明了的原因,为什么Python字典中的键具有该限制。 问题答案: 在我的计算机上,有一个包含大量英语单词的文件: 让我们创建一个字典来存储所有这些单词的长度: 并且,为了踢球,我们将改组原始单词列表: 嗯,滚刀。无论如何…现在我们已经有点混乱了,我们变得有点偏执了(可能出于与渴望滚刀相同的原因),并且我们想检查字典中的所有单词是否都正确。我
问题内容: 我想在Swift中对字典进行排序。我有一本字典,例如: 等,我希望它像 等等 我在SO上尝试了许多解决方案,但没有人为我工作。我正在使用XCode6 Beta 5,在它上面有一些正在给编译器错误,在一些解决方案中有例外。因此,任何可以发布字典排序工作副本的人。 问题答案: 编辑: 上面代码中的排序数组仅包含键,而值必须从原始字典中检索。但是,也是(键,值)对的一对,我们可以使用全局函数