简体   繁体   English

字典和 OrderedDict 之间的区别

[英]Difference between dictionary and OrderedDict

I am trying to get a sorted dictionary.我想得到一个排序的字典。 But the order of the items between mydict and orddict doesn't seem to change.但是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)

As of Python 3.7 , a new improvement to the dict built-in is:Python 3.7 开始,对内置dict的新改进是:

the insertion-order preservation nature of dict objects has been declared to be an official part of the Python language spec. dict 对象的插入顺序保留特性已被声明为 Python 语言规范的官方部分。

This means there is no real need for OrderedDict anymore 🎉.这意味着不再需要OrderedDict 🎉。 They are almost the same.它们几乎相同。


Some minor details to consider...需要考虑的一些小细节...

Here are some comparisons between Python 3.7+ dict and OrderedDict :以下是 Python 3.7+ dictOrderedDict之间的一些比较:

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)

Obviously, there is a difference between the string representation of the two object, with the dict object in more natural and compact form.很明显,这两个对象的字符串表示是有区别的, dict对象的形式更加自然紧凑。

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

As for different methods between the two, this question can be answered with set theory:至于两者的不同方法,这个问题可以用集合论来回答:

d_set = set(dir(d))
od_set = set(dir(od))
od_set.difference(d_set)
# {'__dict__', '__reversed__', 'move_to_end'}  for Python 3.7
# {'__dict__', 'move_to_end'}  for Python 3.8+

This means OrderedDict has at most two features that dict does not have built-in, but work-arounds are shown here:这意味着OrderedDict最多具有两个dict没有内置的功能,但此处显示了变通方法:

Workaround for __reversed__ /reversed() __reversed__ /reversed()解决方法

No workaround is really needed for Python 3.8+, which fixed this issue . Python 3.8+ 确实不需要解决方法,它解决了这个问题 OrderedDict can be "reversed", which simply reverses the keys (not the whole dictionary): OrderedDict可以“反转”,它只是反转键(不是整个字典):

reversed(od)        # <odict_iterator at 0x7fc03f119888>
list(reversed(od))  # ['a', 'b']

# with Python 3.7:
reversed(d)                    # TypeError: 'dict' object is not reversible
list(reversed(list(d.keys()))) # ['a', 'b']

# with Python 3.8+:
reversed(d)        # <dict_reversekeyiterator at 0x16caf9d2a90>
list(reversed(d))  # ['a', 'b']

To properly reverse a whole dictionary using Python 3.7+:要使用 Python 3.7+ 正确反转整个字典:

dict(reversed(list(d.items())))  # {'a': 2, 'b': 1}

Workaround for move_to_end move_to_end解决方法

OrderedDict has a move_to_end method, which is simple to implement: OrderedDict有一个move_to_end方法,实现起来很简单:

od.move_to_end('b')  # now it is: OrderedDict([('a', 2), ('b', 1)])

d['b'] = d.pop('b')  # now it is: {'a': 2, 'b': 1}

An OrderedDict preserves the order elements were inserted: 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)]

So an OrderedDict does not order the elements for you, it preserves the order you give it.所以OrderedDict不会为你排序元素,它会保留你给它的顺序。

If you want to "sort" a dictionary, you probably want如果你想对字典进行“排序”,你可能想要

>>> sorted(d.items())
[('a', 1), ('b', 2), ('c', 3)]

Starting with CPython 3.6 and all other Python implementations starting with Python 3.7, the built-in dict is ordered - you get the items out in the order you inserted them.CPython 3.6开始,以及从 Python 3.7 开始的所有其他 Python 实现,内置的dict是有序的- 您按照插入它们的顺序取出项目。 Which makes dict and OrderedDict effectively the same.这使得dictOrderedDict实际上相同。

The documentation for OrderedDict lists the remaining differences. OrderedDict的文档列出了剩余的差异。 The most important one is that最重要的一点是

  • The equality operation for OrderedDict checks for matching order. OrderedDict的相等操作检查匹配顺序。

Then there's a few minor practical differences:然后有一些小的实际差异:

  • dict.popitem() takes no arguments, whereas OrderedDict.popitem(last=True) accepts an optional last= argument that lets you pop the first item instead of the last item.dict.popitem()接受任何参数,而OrderedDict.popitem(last=True)接受一个可选的last=参数,它允许您弹出第一个项目而不是最后一个项目。
  • OrderedDict has a move_to_end(key, last=True) method to efficiently reposition an element to the end or the beginning. OrderedDict有一个move_to_end(key, last=True)方法可以有效地将元素重新定位到结尾或开头。 With dict s you can move a key to the end by re-inserting it: mydict['key'] = mydict.pop('key')使用dict您可以通过重新插入将键移到最后: mydict['key'] = mydict.pop('key')
  • Until Python 3.8, you could do reversed(OrderedDict()) but reversed({}) would raise a TypeError: 'dict' object is not reversible error because they forgot to add a __reversed__ dunder method to dict when they made it ordered.在 Python 3.8 之前,您可以执行reversed(OrderedDict())reversed({})会引发TypeError: 'dict' object is not reversible错误,因为他们在订购时忘记向dict添加__reversed__ dunder 方法。 This is now fixed.现在已修复。

And there are a few under-the-hood differences that might mean that you could get better performance for some specific usecase with OrderedDict :并且有一些内部差异可能意味着您可以使用OrderedDict为某些特定用例获得更好的性能:

  • The regular dict was designed to be very good at mapping operations.常规dict被设计为非常擅长映射操作。 Tracking insertion order was secondary.跟踪广告订单是次要的。
  • The OrderedDict was designed to be good at reordering operations. OrderedDict旨在擅长重新排序操作。 Space efficiency, iteration speed, and the performance of update operations were secondary.空间效率、迭代速度和更新操作的性能是次要的。
  • Algorithmically, OrderedDict can handle frequent reordering operations better than dict .在算法上, OrderedDict可以比dict更好地处理频繁的重新排序操作。 This makes it suitable for tracking recent accesses (for example in an LRU cache ).这使它适合跟踪最近的访问(例如在LRU 缓存中)。

See this great talk from 2016 by Raymond Hettinger for details on how Python dictionaries are implemented.有关如何实现 Python 词典的详细信息,请参阅Raymond Hettinger 2016 年的精彩演讲

Ordered dictionaries are just like regular dictionaries but they remember the order that items were inserted.有序字典就像普通字典一样,但它们记住插入项目的顺序。 When iterating over an ordered dictionary, the items are returned in the order their keys were first added.迭代有序字典时,项目将按照它们的键首次添加的顺序返回。

So it only sorts by order of adding into the dict所以它只按添加到字典的顺序排序

You can build an OrderedDict order by key as follow,您可以按如下方式构建 OrderedDict 订单,

orddict = OrderedDict(sorted(mydict.items(), key = lambda t: t[0]))

or simply as @ShadowRanger mentioned in comment或者就像评论中提到的@ShadowRanger

orddict = OrderedDict(sorted(d.items()))

If you want to order by value,如果您想按价值订购,

orddict = OrderedDict(sorted(mydict.items(), key = lambda t: t[1]))

More information in 8.3.5.1. 8.3.5.1 中的更多信息 OrderedDict Examples and Recipes OrderedDict 示例和食谱

Adding on to the answer by Brian, OrderedDict is really great.除了 Brian 的回答之外, OrderedDict真的很棒。 Here's why:原因如下:

  • You can use it as simple dict object because it supports equality testing with other Mapping objects like collections.counter .您可以将它用作简单的dict对象,因为它支持与其他Mapping对象(如collections.counter )的相等性测试。

  • OrderedDict preserves the insertion order as explained by Brian. OrderedDict保留了 Brian 所解释的插入顺序。 In addition to that it has a method popitem which returns (key,value) pairs in LIFO order.除此之外,它还有一个popitem方法,它以 LIFO 顺序返回(键,值)对。 So, you can also use it as a mapped 'stack'.因此,您也可以将其用作映射的“堆栈”。

You not only get the full features of a dict but also, some cool tricks.您不仅可以获得dict的全部功能,还可以获得一些很酷的技巧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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