【问题标题】:Does dictionary, json (dumps, loads), defaultdict preserve the order from python 3.7?字典、json(转储、加载)、defaultdict 是否保留了 python 3.7 的顺序?
【发布时间】:2021-06-26 22:39:20
【问题描述】:

我一直认为字典是无序的,这意味着我们必须使用像 OrderedDict 这样的东西来让它记住插入顺序。

当我看到 python 文档时,有人提到从 python 3.7 dict 是有序的。

我对此没有什么疑问,

  1. 如果 dict 保留插入顺序,这是否意味着即使集合中的 defaultdict 也会这样做?
  2. 如果我有下面这样的数据,json.dumps 和 json.loads 功能与 defaultdict 数据怎么样,

编辑:https://docs.python.org/3/library/json.html (json 文档)

在 Python 3.7 之前,不保证 dict 是有序的,所以输入 并且输出通常被打乱,除非 collections.OrderedDict 被特别要求。从 Python 3.7 开始,常规 dict 变成了顺序保留,因此不再需要指定 collections.OrderedDict 用于 JSON 生成和解析。

就第二个疑问而言,我在 python 中找到了上述语句 json docs,但我想知道这是否适用于 嵌套的 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) 

我已经尝试过这些并且它保持秩序,但我想确保无论如何这将始终保持秩序。

【问题讨论】:

  • 试试这个不是更容易吗?
  • 你尝试的时候发生了什么?
  • 文档中说“defaultdict 是内置 dict 类的子类。它覆盖了一个方法并添加了一个可写实例变量。其余功能与 dict 类相同,未记录在这里。”
  • defaultdict 和 JSON 是完全不同的问题——它们属于两个问题。
  • JSON 格式不支持对象排序json.org/json-en.html

标签: python python-3.x


【解决方案1】:

Python 字典

从 python 3.7 开始,dict 的实现被排序为thespecification 的一部分,而不是作为实现的副作用,因此可以可靠地使用它。 OrderedDict 仍然有用有几个原因:

  • 向后兼容性(如果您需要支持较旧的 python 版本)
  • 使用move_to_endpop_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 迭代 超过keys,所以它不应该改变顺序。

如果需要,您可以强制使用字典顺序:

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

关于加载,我不明白为什么订单不会被保留,但我承认我迷失在 decoderscanner 的源代码中。

如果你愿意,你可以使用:

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

嵌套字典

上述内容也适用于嵌套字典:_iterencode_dict 称为 recursively,所有字典的键为 sorted

确实:

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

干杯!

【讨论】:

  • Json.dumps sort_keys 只有在我们有字典的情况下才有效,不是吗?就我而言,我有嵌套的 dict 所以这行不通吗?由于 sort_keys 仅对外部键进行排序。如果您看到我上面提供的示例数据,那就是我拥有的数据类型
  • @user_12 不,它对所有 JSON 对象的键进行排序
  • 我添加了一个关于嵌套字典的部分,它将递归地对键进行排序。
  • @juanpa.arrivillaga 知道了,然后我可以在使用转储或加载时安全地使用 sort_keys。这很有帮助
  • OrderedDict 相对于有序的普通dict 的额外(可能)优势:OrderedDict 的相等性测试与另一个OrderedDict 进行比较时,是对顺序敏感的。 dict 不是(dict == dictdict == OrderedDictOrderedDict == dict 是顺序不敏感的,但OrderedDict == OrderedDict 是顺序敏感的;如果键顺序不匹配,则不相等)。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2015-10-14
  • 2014-08-14
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多