Python 为什么OrderedDict()比dict()和list()慢10倍?
只需运行下面的测试,并注意到填充一个Python 为什么OrderedDict()比dict()和list()慢10倍?,python,python-2.x,Python,Python 2.x,只需运行下面的测试,并注意到填充一个orderedict()大约比填充一个dict()或list()慢一个数量级 为什么? 与: OrderedDict是用纯Python实现的,因此下面是源代码的相关部分: def __setitem__(self, key, value, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y' # Setting a new item creates a
orderedict()
大约比填充一个dict()
或list()
慢一个数量级
为什么?
与:
OrderedDict
是用纯Python实现的,因此下面是源代码的相关部分:
def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
'od.__setitem__(i, y) <==> od[i]=y'
# Setting a new item creates a new link at the end of the linked list,
# and the inherited dictionary is updated with the new key/value pair.
if key not in self:
root = self.__root
last = root[0]
last[1] = root[0] = self.__map[key] = [last, root, key]
return dict_setitem(self, key, value)
def\uuuuu setitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
'od.\uuuu集合项\uuuu(i,y)od[i]=y'
#设置新项目将在链接列表的末尾创建新链接,
#继承的字典将使用新的键/值对进行更新。
如果键不在self中:
根=自身
last=根[0]
最后[1]=根[0]=自身。\u映射[键]=[最后,根,键]
返回dict_setitem(self、key、value)
如果密钥不存在,您将创建一个新列表并访问列表中的两个项目,这将减慢速度。两个原因:
OrderedDict
比dict
要做更多的工作OrderedDict
是,而和是用C编写的第一个我不太确定。它当然提供了一个额外的保证,但是完全针对这些保证的实现不应该导致显著的额外工作(另请参见:几个月前的一个python开发人员或python ideas线程关于dict的更改,该更改在许多情况下会自动保持顺序,并在其他情况下更容易维护)。当然不足以慢一个数量级。@delnan我同意#2比#1重要得多。我还没有研究过
orderedict
的代码,但如果在行为上尽可能接近dict
比在执行上更仔细,我也不会感到惊讶;这至少是Python中的典型方法。@ZeroPiraeus许多非基本类型也有C实现,例如deque
和defaultdict
(保持在collections
)中。python3中的速度差发生了变化,现在OrderedDict只是有点慢,以防有人发现这个问题,只是想有一个保留插入顺序的dict-您不再需要使用OrderedDict。由于Python 3.7,该语言现在需要dict来保留插入顺序https://mail.python.org/pipermail/python-dev/2017-December/151283.html
。谢谢@user136036 True。时光飞逝。
def test_ord_dict():
a = OrderedDict()
for el in xrange(1000):
a[el] = np.random.randint(100)
return a
def test_dict():
a = dict()
for el in xrange(1000):
a[el] = np.random.randint(100)
return a
def test_list():
a = list()
for el in xrange(1000):
a.append(np.random.randint(100))
return a
def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
'od.__setitem__(i, y) <==> od[i]=y'
# Setting a new item creates a new link at the end of the linked list,
# and the inherited dictionary is updated with the new key/value pair.
if key not in self:
root = self.__root
last = root[0]
last[1] = root[0] = self.__map[key] = [last, root, key]
return dict_setitem(self, key, value)