python 3.6与旧版本中的字典顺序

Posted

技术标签:

【中文标题】python 3.6与旧版本中的字典顺序【英文标题】:Dict order in python 3.6 vs older 【发布时间】:2017-11-04 11:14:07 【问题描述】:

当我通过tabulate 运行它时,我需要按照这个确切的顺序(访客团队、访客评级、主队、主场评级、预期获胜者、保证金)打印出这段代码。

final_dict = 'Visitor Team': visitor_team, 'Visitor Rating': visitor_rating, 'Home Team': home_team,
              'Home Rating': home_rating, 'Expected Winner': expected_winner, 'Margin': expected_winner_diff

print(tabulate(final_dict, headers="keys", floatfmt=".2f", tablefmt="fancy_grid"))

我一直在学习和使用 Python 3.6,但我不知道的是,现在订购了 3.6 中的 dicts,所以这实际上按我的意图打印出来。我猜 Python 3.6 正好给了我我需要的东西,这只是运气不好!

但是我在另一台计算机上安装了 Python 3.5,但并没有像我想要的那样打印出来。我一直在阅读有关orderdicts 的信息,但我不确定如何使用它。我是否需要先将 final_dict 声明为空,然后按我需要的键顺序对其进行迭代?

【问题讨论】:

字典不按顺序存储键。如果你想保持顺序,你应该使用一个列表。 您没有提供函数tabulate,但这就是打印完成的地方。这里的重要问题是,tabulate 如何通过final_dict 的元素递增?它如何使用headers的值来控制打印顺序?它如何知道字典的哪个元素匹配哪个标题?我认为您应该查看tabulate 以了解它是如何工作的。否则无法保证更改为 OrderedDict 会解决您的问题。 @PaulCornelius 这些都是好点。 tabulate 是一个用于打印表格输出的包:pypi.python.org/pypi/tabulate 我没有写它,所以我不确定它的“内部”是如何工作的。 文档pypi.python.org/pypi/tabulate 说制表的第一个参数可以是列表的列表。这似乎是控制列顺序的唯一可靠方法。由于这对您很重要,因此我会将您的数据转换为列表列表,然后再将其传递给列表。 相关***.com/questions/39980323/… 【参考方案1】:

Python 3.6 中的字典是有序的,但该功能被视为您不应依赖的实现细节(除了**kwargs 等少数特定情况)。如果您确实需要特定订单,则应改用collections.OrderedDict。您可以使用按所需顺序排列的key, value 元组列表构建一个:

from collections import OrderedDict

finaldict = OrderedDict([('Visitor Team', visitor_team),
                         ('Visitor Rating', visitor_rating),
                         ('Home Team', home_team),
                         ('Home Rating', home_rating),
                         ('Expected Winner', expected_winner),
                         ('Margin', expected_winner_diff),
                        ])

OrderedDict 在大多数方面与普通的dict 一样,除了具有不同的repr 和一些其他方法。您可以在the docs 阅读更多相关信息。

在 Python 3.6+ 中,如果您的键字符串是有效的标识符(例如 OrderedDict(Margin=expected_winner_diff)),您还可以对构造函数使用关键字参数。与普通dicts 的顺序不同,关键字的顺序保证被保留(不是实现细节)。但是,这不是向后兼容的(无论如何也不能用于您的非标识符键)。

但可能值得考虑的是,如果您需要非常具体的数据顺序,字典可能不是存储数据的最佳类型。我看到您使用的 tabulate 函数来自库,并且根据文档,它接受许多不同格式的数据。我可能只是将列数据列表传递给它,并分别给它标题:

data = [visitor_team, visitor_rating, home_team,
        home_rating, expected_winner, expected_winner_diff]

headers = ["Visitor Team", "Visitor Rating", "Home Team",
           "Home Rating", "Expected Winner", "Margin"]

print(tabulate(data, headers=headers, floatfmt=".2f", tablefmt="fancy_grid"))

(请注意,我没有实际测试过该代码,因为我的系统上没有 tabulate 库。但它至少应该接近工作。)

【讨论】:

文档说data 必须是二维数据类型,例如列表列表或列表字典。一个简单的列表是行不通的。我猜 OP 的原始代码可以工作,因为他所有的字典值实际上都是列表。 @PaulCornelius 是的,这是正确的。所有这些都存储为列表。我会玩弄我所拥有的,看看我能想出什么。 我最终只是将我的 finaldict 转换为一个列表。我认为只处理列表而不是弄乱让orderdict工作要容易得多。谢谢你们的帮助!

以上是关于python 3.6与旧版本中的字典顺序的主要内容,如果未能解决你的问题,请参考以下文章

Python 3.6 和 Python 3.5 中字典顺序之间的差异 [重复]

在 Python 3.6+ 中有效地按位置访问字典项

Python中的字典有序无序浅析

使用 python 3.6 将多个文件并行加载到内存中的最佳方法是啥?

七天学会Python基础-第二天1/1

字典和枚举