python中字典和ordereddict之间的区别

liv*_*hak 11 python dictionary ordereddictionary python-2.7 python-3.x

我想要一个排序的字典.但之间的项目的顺序mydictorddict似乎并没有改变.

from collections import OrderedDict

mydict = {'a':1,'b':2,'c':3,'d':4}

orddict = OrderedDict(mydict)

print(mydict,orddict)

# print items in mydict:
print('mydict')
for k,v in mydict.items():
    print(k,v)

print('ordereddict')
# print items in ordered dictionary
for k,v in orddict.items():
    print(k,v)


# print the dictionary keys
# for key in mydict.keys():
#     print(key)


#  print the dictionary values
# for value in mydict.values():
#     print(value)
Run Code Online (Sandbox Code Playgroud)

Bri*_*orn 11

一个OrderedDict保留的顺序的元件插入:

>>> od = OrderedDict()
>>> od['c'] = 1
>>> od['b'] = 2
>>> od['a'] = 3
>>> od.items()
[('c', 1), ('b', 2), ('a', 3)]
>>> d = {}
>>> d['c'] = 1
>>> d['b'] = 2
>>> d['a'] = 3
>>> d.items()
[('a', 3), ('c', 1), ('b', 2)]
Run Code Online (Sandbox Code Playgroud)

所以a OrderedDict不会为你订购元素,它会保留 你给它的顺序.

如果你想"排序"字典,你可能想要

>>> sorted(d.items())
[('a', 1), ('b', 2), ('c', 3)]
Run Code Online (Sandbox Code Playgroud)

  • @RakshitKothari 是的,有!请参阅其他答案 - 在 Python 3.7+ 中,“dict”现在的行为与“OrderedDict”相同。 (4认同)
  • 并且要将`dict`转换为`OrderedDict`(最初)具有按排序顺序的键,你可以:`od = OrderedDict(sorted(d.items()))`. (2认同)
  • 请注意,默认情况下,字典现在按插入顺序排序。 (2认同)

Mik*_*e T 7

Python 3.7开始,新的改进是:

dict对象的插入顺序保留性质已声明是Python语言规范的正式组成部分。

这意味着OrderedDict不再需要。它们几乎相同。


但是,需要考虑一些小细节...

但是,Python 3.7+ dict和之间存在差异OrderedDict,此处显示:

from collections import OrderedDict

d = {'b': 1, 'a': 2}
od = OrderedDict([('b', 1), ('a', 2)])

# they are equal with content and order
assert d == od
assert list(d.items()) == list(od.items())
assert repr(dict(od)) == repr(d)
Run Code Online (Sandbox Code Playgroud)

显然,两个对象的字符串表示形式之间存在差异,而dict对象的形式更自然,更紧凑。

str(d)  # {'b': 1, 'a': 2}
str(od) # OrderedDict([('b', 1), ('a', 2)])
Run Code Online (Sandbox Code Playgroud)

至于两者之间的不同方法,可以用集合论来回答这个问题:

d_set = set(dir(d))
od_set = set(dir(od))
od_set.difference(d_set)
# {'__dict__', '__reversed__', 'move_to_end'}
Run Code Online (Sandbox Code Playgroud)

这意味着OrderedDict至少具有两个dict内置功能,但此处显示了解决方法:

# 1) OrderedDict can be reversed (but then what?)
reversed(od)
# <odict_iterator at 0x7fc03f119888>
reversed(d)
# TypeError: 'dict' object is not reversible
# better way to reverse a dict
dict(reversed(list(d.items())))  # {'a': 2, 'b': 1}

# 2) OrderedDict has 'move_to_end' method
od.move_to_end('b')  # now it is: OrderedDict([('a', 2), ('b', 1)])
# dict does not, but similar can be done with
d['b'] = d.pop('b')  # now it is: {'a': 2, 'b': 1}
Run Code Online (Sandbox Code Playgroud)


Bor*_*ris 6

CPython 3.6开始,以及从 Python 3.7 开始的所有其他 Python 实现,内置dict函数是有序的- 您按照插入它们的顺序取出项目。这使得dictOrderedDict有效相同。

的文档OrderedDict列出了剩余的差异。最重要的一点是

  • 用于OrderedDict检查匹配顺序的相等操作。

然后有一些小的实际差异:

  • dict.popitem()OrderedDict.popitem(last=True)接受任何参数,而接受一个可选last=参数,让您弹出第一个项目而不是最后一个项目。
  • OrderedDict有一种move_to_end(key, last=True)方法可以有效地将元素重新定位到结尾或开头。使用dicts 您可以通过重新插入将键移到最后:mydict['key'] = mydict.pop('key')
  • 在 Python 3.8 之前,您可以这样做,reversed(OrderedDict())reversed({})会引发TypeError: 'dict' object is not reversible错误,因为他们在订购时忘记添加__reversed__dunder 方法dict。现在已修复。

并且有一些内部差异可能意味着您可以通过以下方式为某些特定用例获得更好的性能OrderedDict

  • 常规dict被设计为非常擅长映射操作。跟踪广告订单是次要的。
  • OrderedDict设计要善于重新排序操作。空间效率、迭代速度和更新操作的性能是次要的。
  • 在算法上,OrderedDict可以比 更好地处理频繁的重新排序操作dict。这使它适合跟踪最近的访问(例如在LRU 缓存中)。

有关如何实现 Python 词典的详细信息,请参阅Raymond Hettinger 2016 年的精彩演讲