簡體   English   中英

OrderedDict與Python中的Dict

[英]OrderedDict vs Dict in python

蒂姆彼得的答案中 ,“有沒有理由不使用有序詞典”,他說

OrderedDict是dict的子類。

它的速度並不慢很多,但至少使用普通字典使內存翻倍。

現在,在經歷一個特定的問題時 ,我嘗試使用ipython一些樣本檢查,並且兩者都與之前的推理相矛盾:

  1. dictOrderedDict的大小相同
  2. OrderedDict上操作比在dict上操作時容易大約7-8倍(因此慢很多)

有人可以向我解釋我在推理中出錯的地方嗎?


創建一個大型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

我認為大小的問題是由於在OrderedDict Python 2.X 實現中沒有定義__sizeof__方法的事實,所以它簡單地回退到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中修復的,現在有一個定義良好的__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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM