[英]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.但是mydict
和orddict
之间的项目顺序似乎没有改变。
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.它们几乎相同。
Here are some comparisons between Python 3.7+ dict
and 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)
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
没有内置的功能,但此处显示了变通方法:
__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}
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.这使得dict
和OrderedDict
实际上相同。
The documentation for OrderedDict
lists the remaining differences. OrderedDict
的文档列出了剩余的差异。 The most important one is that最重要的一点是
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')
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
为某些特定用例获得更好的性能:
dict
was designed to be very good at mapping operations.常规dict
被设计为非常擅长映射操作。 Tracking insertion order was secondary.跟踪广告订单是次要的。OrderedDict
was designed to be good at reordering operations. OrderedDict
旨在擅长重新排序操作。 Space efficiency, iteration speed, and the performance of update operations were secondary.空间效率、迭代速度和更新操作的性能是次要的。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.