Сохраняет ли dictionary, json (dumps, loads), defaultdict порядок из python 3.7?

#python #python-3.x

#python #python-3.x

Вопрос:

Я всегда думал, что словари неупорядочены, это означает, что мы должны были использовать что-то вроде OrderedDict, чтобы заставить его запоминать порядок вставки.

Когда я увидел документы python, было упомянуто, что из python 3.7 dict упорядочен.

У меня мало сомнений в этом,

  1. Если dict сохраняет порядок вставки, означает ли это, что даже коллекции defaultdict in также будут делать то же самое?
  2. Как насчет функций json.dumps и json.loads с данными defaultdict, если у меня есть данные, подобные приведенным ниже,

РЕДАКТИРОВАТЬ: https://docs.python.org/3/library/json.html (документация json)

До Python 3.7 порядок dict не гарантировался, поэтому входные и выходные данные обычно скремблировались, если не было коллекций.Специально был запрошен OrderedDict . Начиная с Python 3.7, обычный dict стал сохранять порядок, поэтому больше нет необходимости указывать коллекции.OrderedDict для генерации и синтаксического анализа JSON.

Что касается второго сомнения, я нашел приведенное выше утверждение в документах python json, но я хотел знать, будет ли это применимо для вложенных данных defaultdict.

 # example defaultdict data for 2 doubt. 

from collections import defaultdict
data = defaultdict(dict)

data["0"]["a"] = "Google"
data["0"]["b"] = "Google"
data["0"]["c"] = "Google"
data["1"]["a"] = "Google"
data["1"]["b"] = "Google"
data["1"]["c"] = "Google"
data["2"]["a"] = "Google"
data["2"]["b"] = "Google"
data["2"]["c"] = "Google"
data["3"]["c"] = "Google"
data["3"]["b"] = "Google"
data["3"]["a"] = "Google"

json.dumps(data) # will these operations preserve the order 
json.loads(data) 

 

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

Комментарии:

1. Разве не было бы проще просто попробовать это?

2. Что произошло, когда вы попробовали это?

3. В документации говорится: » defaultdict является подклассом встроенного класса dict . Он переопределяет один метод и добавляет одну переменную экземпляра, доступную для записи. Остальные функциональные возможности такие же, как и для класса dict, и здесь не документированы. »

4. defaultdict и JSON — это совершенно разные проблемы — они относятся к двум вопросам.

5. Формат JSON не поддерживает порядок в объектах json.org/json-en.html

Ответ №1:

Python диктует

Начиная с python 3.7, реализация dict упорядочивается как часть спецификации, а не как побочный эффект реализации, поэтому ее можно использовать надежно. OrderedDict по-прежнему полезен по нескольким причинам:

  • обратная совместимость (если вам нужно поддерживать более старые версии python)
  • измените порядок ключей с помощью move_to_end и pop_item
  • более четкое намерение: если вы полагаетесь на то, что ключи dict упорядочены, OrderedDict делает это очевидным, но вы теряете некоторую производительность
  • порядок ключей учитывается при сравнении OrderedDicts и игнорируется для dicts (спасибо @ShadowRanger за уведомление):

Например:

 from collections import OrderedDict

one_dict = {"a": 1, "b": 2}
another_dict = {"b": 2, "a": 1}

one_ordered_dict = OrderedDict(a=1, b=2)
another_ordered_dict = OrderedDict(b=2, a=1)

print(one_dict == another_dict)
# True
print(one_ordered_dict == another_ordered_dict)
# False
 

Если требуется какое-либо из этих требований, вам может помочь OrderedDict , иначе вы можете просто использовать обычный dict .

Дамп / загрузка Json

Что касается json.dump , это другой вопрос:

Насколько я могу судить, JSONEncoder итерации по ключам, поэтому порядок не должен меняться.

Вы можете принудительно установить лексикографический порядок, если хотите:

 >>> json.dumps({'b': 1, 'a': 2}, sort_keys=True)
'{"a": 2, "b": 1}'
 

Что касается загрузки, я не понимаю, почему порядок не будет сохранен, но я признаю, что теряюсь в исходном коде для декодера и сканера.

Если вы хотите, вы можете использовать:

 >>> json.loads('{"b": 2, "a": 1}', object_pairs_hook=OrderedDict)
OrderedDict([('b', 2), ('a', 1)])
 

Вложенные dicts

Вышесказанное применимо и к вложенным dicts: _iterencode_dict вызывается рекурсивно, и ключи сортируются для всех dicts.

Действительно:

 >>> json.dumps({'b': 1, 'a': {'d': 1, 'c': 3}}, sort_keys=True)
'{"a": {"c": 3, "d": 1}, "b": 1}'
 

Приветствия!

Комментарии:

1. Json.dumps sort_keys будет работать, только если у нас есть dict, не так ли? В моем случае у меня есть вложенный dict, так что это не сработает правильно? Поскольку sort_keys сортирует только внешние ключи. Если вы видите пример данных, которые я привел выше, это тот тип данных, который у меня есть

2. @user_12 нет, он сортирует ключи всех объектов JSON

3. Я добавил раздел, касающийся вложенных dicts, он будет рекурсивно сортировать ключи.

4. @juanpa.arrivillaga Понял, тогда я могу безопасно использовать sort_keys всякий раз, когда я использую дамп или загрузку. Это полезно

5. Дополнительное (возможное) преимущество по OrderedDict сравнению с обычными обычными dict : OrderedDict тесты на равенство при сравнении с другими OrderedDict зависят от порядка. dict нет ( dict == dict или dict == OrderedDict или OrderedDict == dict не зависит от порядка, но чувствителен к порядку OrderedDict == OrderedDict ; если порядок ключей не совпадает, он не будет равен).