使用有序字典作为有序集

Nat*_*aul 8 python python-3.x dictionary-comprehension python-3.7

既然Python 3.7使得保留顺序的dicts 正式成为语言规范的一部分而不是实现细节,那么我一直在努力探讨如何最好地使用这个属性.今天,我发现我需要一个订单保留集,并认为字典可以做到这一点.

假设我们有一个hashable元素列表.我们需要一个唯一条目列表,我们希望根据首次出现保留这些条目的顺序.一个简单的字典构造函数应该做的伎俩:

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']
Run Code Online (Sandbox Code Playgroud)

这将通过首次出现保留排序并消除所有重复.

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

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

通过Python的Zen阅读,我很矛盾.该方法很简单,但依赖于隐式排序.

请让我知道你在想什么.谢谢.

wim*_*wim 6

这种使用Python 3.7字典作为保留订单的重复数据删除的方法由核心Python开发人员在此处进行审查.你不可能真正得到比这更好的建议.

有没有理由不使用这种方法?

没有.

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

没有.

这种方法是Pythonic吗?

是.

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

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


use*_*ica 6

这在Python 3.7上很有用!但是Python 3.7并不是唯一的Python版本.依赖于字典顺序保存很长一段时间会成为一种危险的习惯,因为如果你的代码在3.6之前的Python版本上运行,那么它将完全默默地停止维护秩序.

依赖于,比方说,dataclasses或者contextvars不是任何接近危险的地方,因为如果你试图运行依赖于dataclasses没有的Python的代码dataclasses,你会得到一个很大的,清晰的ImportError.丢失订单的Dicts与它没有相同的显而易见性.

你可能不知道它已停止维持秩序.您可能不记得您依赖于字典顺序.你可能忘记记录或告诉任何你依赖它的人,或者你可能是一个糟糕的程序员,他们继承了其他人依赖于字典顺序的代码而没有记录Python 3.7+的要求.你可能根本不知道你忘了在一台特定的机器上更新Python,或者你不小心退出了Anaconda或其他任何你正在使用3.4的系统Python 3.

最终可以安全地假设字典顺序.目前,特别是现在,在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))
Run Code Online (Sandbox Code Playgroud)