小编典典

python中的OrderedDict vs Dict

python

他说,在蒂姆·彼得(Tim
Peter)的回答中
,“是否有任何理由不使用有序词典”

OrderedDict是dict的子类。

它并没有慢很多,但是至少比使用普通字典要多一倍的内存。

现在,当遇到一个特定问题时,我尝试使用进行了一些示例检查ipython,但它们都与先前的推理相矛盾:

  1. dictOrderedDict相同尺寸的
  2. OrderedDict在s上进行操作所需的时间比在s上进行操作所需的时间轻松大约多了7-8倍dict(因此,速度要慢得多)

有人可以向我解释我的推理哪里出问题了吗?


创建一个大Dict和OrderedDict并比较大小:

import sys
import random
from collections import OrderedDict

test_dict = {}
test_ordered_dict = OrderedDict()

for key in range(10000):
    test_dict[key] = random.random()
    test_ordered_dict[key] = random.random()

sys.getsizeof(test_dict)
786712

sys.getsizeof(test_ordered_dict)
786712

使用以下命令检查插入时间%timeit

import sys
import random
from collections import OrderedDict

def operate_on_dict(r):
    test_dict = {}
    for key in range(r):
        test_dict[key] = random.random()

def operate_on_ordered_dict(r):
    test_ordered_dict = OrderedDict()
    for key in range(r):
        test_ordered_dict[key] = random.random()

%timeit for x in range(100): operate_on_ordered_dict(100)
100 loops, best of 3: 9.24 ms per loop

%timeit for x in range(100): operate_on_dict(100)
1000 loops, best of 3: 1.23 ms per loop

阅读 225

收藏
2021-01-16

共1个答案

小编典典

我认为大小的问题是由于__sizeof__在Python
2.X的实现中OrderedDict没有定义方法的事实,所以它只是退回到dict的__sizeof__方法。

为了在这里证明这一点,我在这里创建了一个A扩展的类,list并且还添加了一个额外的方法foo来检查是否影响大小。

class A(list):
    def __getitem__(self, k):
        return list.__getitem__(self, k)
    def foo(self):
        print 'abcde'

>>> a = A(range(1000))
>>> b = list(range(1000))

但仍返回相同的大小sys.getsizeof

>>> sys.getsizeof(a), sys.getsizeof(b)
(9120, 9120)

当然A会很慢,因为它的方法在Python中运行,而list的方法将在纯C中运行。

>>> %%timeit
... for _ in xrange(1000):
...     a[_]
... 
1000 loops, best of 3: 449 µs per loop
>>> %%timeit
for _ in xrange(1000):
    b[_]
... 
10000 loops, best of 3: 52 µs per loop

这似乎在Python 3中已得到修复,该Python
3中现在有一个定义明确的__sizeof__方法:

def __sizeof__(self):
    sizeof = _sys.getsizeof
    n = len(self) + 1                       # number of links including root
    size = sizeof(self.__dict__)            # instance dictionary
    size += sizeof(self.__map) * 2          # internal dict and inherited dict
    size += sizeof(self.__hardroot) * n     # link objects
    size += sizeof(self.__root) * n         # proxy objects
    return size
2021-01-16