为什么字典排序是不确定的?

2024-05-10

我最近从 Python 2.7 切换到 Python 3.3,似乎在 Python 2 中,字典键的顺序是任意但一致的,而在 Python 3 中,通过例如获得的字典键的顺序是:vars() https://docs.python.org/3/library/functions.html#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']

… ?



Update:在Python 3.6中,dict has a 新的实施 https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-compactdict它保留插入顺序。从 Python 3.7 开始,这种保序行为是保证 https://docs.python.org/3/whatsnew/3.7.html:

插入顺序保存性质dict https://docs.python.org/3/library/stdtypes.html#typesmapping物体已宣布 https://mail.python.org/pipermail/python-dev/2017-December/151283.html成为 Python 语言规范的正式部分。


这是一个结果安全修复 http://mail.python.org/pipermail/python-announce-list/2012-March/009394.html从 2012 年开始,即默认启用 http://docs.python.org/3/whatsnew/3.3.html在 Python 3.3 中(向下滚动到“安全改进”)。

从公告来看:

哈希随机化导致字典和集合的迭代顺序为 不可预测,并且在不同的 Python 运行中有所不同。 Python从来不保证 字典或集合中键的迭代顺序,建议应用程序永远不要 依靠它。从历史上看,字典迭代顺序并没有经常改变 发布并在连续执行之间始终保持一致 Python。因此,一些现有的应用程序可能依赖于字典或集合排序。 因此,许多 Python 应用程序不接受 在所有稳定的 Python 版本中,不受信任的输入不易受到此攻击 这里提到,哈希随机化默认是禁用的。

如上所述,最后一个大写位在 Python 3.3 中不再适用。

也可以看看: object.__hash__()文档 http://docs.python.org/3/reference/datamodel.html#object.__hash__(“注意”侧边栏)。

如果绝对必要,您可以在受此行为影响的 Python 版本中禁用哈希随机化,方法是设置PYTHONHASHSEED https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED环境变量为0.


你的反例:

list({str(i): i for i in range(10)}.keys())

… does not事实上,在 Python 3.3 中总是给出相同的结果,尽管不同排序的数量是有限的due to https://stackoverflow.com/q/26136894/1014938处理哈希冲突的方式:

$ 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']
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么字典排序是不确定的? 的相关文章

随机推荐

  • Java中非对齐指针被释放?

    在 Objective C 中这很容易追踪 但在 Java 中我认为这种事情是不可能的 我看到的错误是 java 7198 0x124a13000 malloc error for object 0x1003109c1 Non aligne
  • MVC .NET 如何为现有源代码添加单元测试项目?

    我已经创建了 MVC 项目 VS2008 NET 3 5 第一次VS2008问我 您想为此应用程序创建单元测试项目吗 我选择否 现在我意识到它变得越来越复杂 TDD 测试驱动开发 方法会更好 但无法找到如何在我的解决方案中添加单元测试项目
  • SlideUp() 在 jQuery 中如何工作?我正在尝试制作自己的slideRight()

    我看过jquery 中幻灯片的源代码 https github com jquery jquery blob master src effects js Generate shortcuts for custom animations jQ
  • 使用 pg-promise 进行多行插入

    我想用一个插入多行INSERT查询 例如 INSERT INTO tmp col a col b VALUES a1 b1 a2 b2 有没有一种方法可以轻松地做到这一点 最好是对于像这样的对象数组 col a a1 col b b1 co
  • 导出 Azure SQL 数据库时出现错误 SQL71501

    导出 Azure SQL 数据库时出现奇怪的错误 导出一直工作正常 直到最近发生一些架构更改 但现在出现错误 SQL71501 该数据库是V12 兼容性级别130 尽管master数据库仍兼容级别 120 该问题似乎是由一个新的表值函数引起
  • 获取监视器数量

    我有一个网络应用程序 我想实现以下行为 当您单击特定链接时 如果用户有多个监视器 在具有给定名称的窗口中打开 URL 否则 将 iframe 的 src 属性更改为 url 的属性 如何在 JavaScript 中检测监视器计数 如果不可能
  • QT 中只获取文件而不获取目录?

    当我这样做时 QDir myDir home some location QStringList filesList myDir entryList 它返回该位置内的文件和目录 但我只想要文件 并且这些文件可以具有任意扩展名 有任何想法吗
  • 活动/非活动 Jquery 导航菜单

    我不熟悉 javascript 所以如果有人可以帮助我 我将非常感激 我有一个像这样的简单列表 ul li Menu 1 li li Menu 2 li li Menu 3 li ul 当用户单击菜单元素时 我想添加一个类 menu act
  • 检测视频何时缓冲,如果缓冲则显示 gif

    我想知道是否有办法在视频缓冲时显示 gif 我正在使用 HTML5 视频标签 其中有一种方法可以检测视频何时缓冲 如果没有 是否有替代方法 我看过 如何检测视频何时缓冲 https stackoverflow com questions 1
  • 有没有办法在 Windows 上全局安装 Composer?

    我读过全局安装文档 http getcomposer org doc 00 intro md globally对于 Composer 但仅适用于 nix 系统 curl s https getcomposer org installer p
  • Rails 中的多列主键

    我正在尝试将桌面应用程序迁移到rails 还处理相当老式的现有数据库 问题是我在一列中没有唯一的 ID 但表的三列保证了记录的唯一性 鉴于我有三个表 authors author name author letter author nr1
  • 此集合实例 Laravel 关系中不存在属性 [X]

    我在 Laravel 5 6 中使用了很多 Realtions 当我添加 phonebooks 时 我看到所有关系都工作正常 一切都很好 但是当我尝试在视图中显示它们时 我得到了属性在此集合上不存在的错误 这是关系代码 public fun
  • Eclipse,在哪里更改当前调试行背景?

    任何人都可以向我指出具有以下设置的首选项页面DEBUG当前行背景颜色 我已经将几乎所有颜色更改为深色 但在调试时仍然对这个几乎白色的当前行指示器感到恼火 请注意 编辑模式下的当前行指示是可以的 好吧 现在我自己找到了它 通过主要的逆向工程
  • Accounts.onCreateUser 在创建新用户时添加额外属性,好的做法吗?

    我正在创建新用户Accounts createUser http docs meteor com full accounts createuser如果你不做任何花哨的事情 它就会正常工作 但我想向新用户添加一些文档中未列出的其他字段 这是我
  • 如何在 JavaScript 中访问“关联”数组的第一个键?

    我有一个 js 关联 数组 其中 array serial number value serial number 和 value 是字符串 例如array 20910930923 20101102 我按价值排序 效果很好 假设我取回了 已排
  • 了解 std::swap()。 tr1::_Remove_reference 的目的是什么?

    在 VS10 的 STL 实现中 有以下 std swap 变体的代码 TEMPLATE FUNCTION Move template
  • 如果 AWS API 请求失败,我如何调试我需要哪些权限?

    我正在使用 Terraform 在 AWS 上配置一些资源 运行 Terraform 的 计划 步骤失败 并出现以下模糊错误 例如 Error Error loading state AccessDenied Access Denied s
  • WPF鼠标按下事件没有坐标

    我在控件上使用 WPF 鼠标按下事件 我想获取 X Y 坐标 但出现错误 private void button MouseDown object sender MouseButtonEventArgs e double x e X dou
  • Mongoid 4 / MongoDB 2.4+“冻结”问题

    自从使用 Mongoid 维护与 mongodb 的连接以来 我遇到了一个奇怪的问题 我认为这最初是由于升级到 Rails 4 0 需要更新 Mongoid Moped 但我在其他基于 Rack 的应用程序 具体来说是 Sinatra 和
  • 为什么字典排序是不确定的?

    我最近从 Python 2 7 切换到 Python 3 3 似乎在 Python 2 中 字典键的顺序是任意但一致的 而在 Python 3 中 通过例如获得的字典键的顺序是 vars https docs python org 3 li