12

既然 Python 3.7 使保留顺序的字典正式成为语言规范的一部分,而不是实现细节,我一直在努力思考如何最好地使用这个属性。今天,我发现我需要一个订单保留集,并认为字典可以解决问题。

假设我们有一个可散列元素的列表。我们想要一个唯一条目的列表,并且我们希望根据第一次出现来保持这些条目的顺序。一个简单的字典构造函数应该可以解决问题:

ls = "Beautiful is better than ugly. Explicit..."
uniques = list({s:0 for s in ls})

>>> ['B', 'e', 'a', 'u', 't', 'i', 'f', 'l', ' ', 's', 'b', 'r', 'h', 'n', 'g', 'y', '.', 'E', 'x', 'p', 'c']

这将保留第一次出现的顺序并消除所有重复项。

我想知道社区对这个用例的看法以及一般的订单保留功能。

  • 有什么理由不应该使用这种方法吗?
  • 有没有更好的方法来解决这个问题?
  • 这种方法是 Pythonic 的吗?

通读Python之禅,我很矛盾。该方法很简单,但依赖于隐式排序。

请让我知道你的想法。谢谢你。

4

2 回答 2

7

这种使用 Python 3.7 字典作为保持顺序的重复数据删除的方法在此处由核心 Python 开发人员进行了审查。你真的找不到比这更好的推荐了。

有什么理由不应该使用这种方法吗?

不。

有没有更好的方法来解决这个问题?

不。

这种方法是 Pythonic 的吗?

是的。

该方法很简单,但依赖于隐式排序。

您的问题被标记为 python-3.7。保证保留插入顺序的字典,因此这里没有隐式排序。

于 2018-07-03T02:07:39.143 回答
6

这在 Python 3.7 上效果很好!.. 但 Python 3.7 并不是唯一的 Python 版本。在很长一段时间内,依赖 dict 顺序保存将是一个危险的习惯,因为如果您的代码曾经在 3.6 之前的 Python 版本上运行,它将完全静默地停止维护顺序。

比如说,依赖dataclasses或者没有那么危险,contextvars因为如果你尝试运行依赖于dataclasses没有. 失去订单的字典并没有同样的明显性。dataclassesImportError

你可能不知道它已经停止维持秩序。你可能不记得你依赖于 dict 命令。您可能忘记记录或告诉任何人您依赖它,或者您可能是一个可怜的编码员,在没有记录 Python 3.7+ 要求的情况下继承了其他人依赖 dict 顺序的代码。您可能不知道自己忘记在一台特定机器上更新 Python,或者您不小心退出了 Anaconda 或其他任何事情,而您使用的系统 Python 3 仍在使用 3.4。

最终假设 dict 命令是安全的。现在,尤其是现在,在 3.7 发布几天后,使用OrderedDict或添加版本检查是一个更好的主意:

import collections
import sys

_make_ordered_mapping = (dict.fromkeys if sys.version_info >= (3, 7)
                         else collections.OrderedDict.fromkeys)

def ordered_dedup(items):
    return list(_make_ordered_mapping(items))
于 2018-07-03T02:47:54.817 回答