Использование упорядоченного словаря как упорядоченного набора

теперь, когда Python 3.7 делает сохраняющие порядок дикты официально часть спецификации языка вместо детали реализации, я пытался обернуть голову вокруг того, как лучше всего использовать это свойство. Сегодня я обнаружил, что мне нужен набор для сохранения порядка, и думаю, что словарь может сделать трюк.

Предположим, у нас есть список элементов 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']

это сохранит заказ по первому появлению и избавится от всех дубликатов.

Я хотел бы знать, что сообщество думает об этом случае использования и порядок сохранения объекта в целом.

  • есть ли причина, по которой этот метод не следует использовать?
  • есть ли лучшие способы решить эту проблему?
  • это подходящие для Python способ?

чтение через Дзен питона я нахожусь в конфликте. Метод прост, но основан на неявном упорядочении.

пожалуйста, дайте мне знать, что вы думаете. Спасибо.

2 ответов


этот подход использования словаря Python 3.7 В качестве де-dupe для сохранения порядка проверяется разработчиком core Python здесь. Вы не можете получить лучшую рекомендацию, чем эта.

есть ли причина, по которой этот метод не следует использовать?

нет.

есть ли лучшие способы решить эту проблему?

нет.

Это способ Для Python?

да.

метод прост, но основан на неявном упорядочении.

ваш вопрос помечен как python-3.7. Словари, сохраняющие порядок вставки, гарантированы, поэтому здесь нет неявного порядка.


это отлично работает на Python 3.7!.. но Python 3.7-не единственная версия Python. Полагаться на сохранение порядка dict будет опасной привычкой довольно долго, потому что, если ваш код когда-либо будет работать на версии Python до 3.6, он перестанет поддерживать порядок, полностью молча.

опираясь на, скажем, dataclasses или contextvars не так опасно, потому что если вы попытаетесь запустить код, который полагается на dataclasses на Python, который не имеет dataclasses, вы получите большой, ясно!--5-->. Дикты, теряющие свой порядок, не имеют такой же очевидности.

вы, возможно, понятия не имеете, что он перестал поддерживать порядок. Возможно, вы не помните, что полагались на приказ диктатора. Вы можете забыть документировать или сказать кому-либо, что вы полагались на него, или вы можете быть плохим кодером, который наследует код, где кто-то другой полагался на порядок dict без документирования требования Python 3.7+. Возможно, вы не знаете, что забыли обновить 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))