简体   繁体   中英

Using ordered dictionary as ordered set

Now that Python 3.7 makes order-preserving dicts officially part of the language spec instead of an implementation detail, I've been trying to wrap my head around how best to use this property. Today, I've found I needed an order preserving set and think the dictionary might do the trick.

Suppose we have a list of hashable element. We want a list of unique entries and we want to keep the order of these entries based on first appearance. A simple dictionary constructor should do the trick:

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']

This will preserve the ordering by first appearance and get rid of all duplicates.

I'd like to know what the community thinks of this use case and the order preserving feature in general.

  • Is there any reason this method shouldn't be used?
  • Are there better ways to solve this problem?
  • Is this method Pythonic?

Reading through the Zen of Python, I am conflicted. The method is simple but relies on implicit ordering.

Please let me know what you think. Thank you.

This approach of using a Python 3.7 dictionary as an order-preserving de-dupe is vetted by a core Python developer here . You can't really get a better recommendation than that.

Is there any reason this method shouldn't be used?

No.

Are there better ways to solve this problem?

No.

Is this method Pythonic?

Yes.

The method is simple but relies on implicit ordering.

Your question is tagged python-3.7. Dictionaries preserving insertion order is guaranteed, so there is not an implicit ordering here.

This works great on Python 3.7!.. but Python 3.7 isn't the only Python version around. Relying on dict order preservation is going to be a dangerous habit for quite a while, because if your code ever runs on a Python version before 3.6, it'll stop maintaining order, completely silently.

Relying on, say, dataclasses or contextvars isn't anywhere near as dangerous, because if you try to run code that relies on dataclasses on a Python that doesn't have dataclasses , you get a big, clear ImportError . Dicts losing their order doesn't have the same obviousness to it.

You may have no idea it's stopped maintaining order. You may not remember you relied on dict order. You might forget to document or tell anyone that you relied on it, or you might be the poor coder who inherits code where someone else relied on dict order without documenting the Python 3.7+ requirement. You may have no idea you forgot to update Python on one particular machine, or that you accidentally dropped out of Anaconda or whatever and you're on the system Python 3 that's still using 3.4.

It'll be safe to assume dict order eventually. For now, especially right now , a few days after the release of 3.7, it's a better idea to use OrderedDict , or add a version check:

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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM