为什么list.remove比列表理解更快?

时间:2017-05-11 09:08:21

标签: python python-2.7

我不喜欢以下从列表中删除元素的方法:

try:
    lst.remove(elt)
except ValueError:
    pass

我知道在Python中使用try除了块并且我实际上使用它们是可以的,但在这种特殊情况下我希望有一个list.remove_if_exists(elt)方法,当我不需要处理这个案例时当元素不在列表中时。

为了让事情更清楚,我尝试使用列表理解:

lst = [x for x in lst if x != elt]

然而,结果却变慢了:

In [3]: %timeit [x for x in lst if x != elt]
1000 loops, best of 3: 334 µs per loop

In [4]: %timeit lst[:].remove(elt)
10000 loops, best of 3: 42.8 µs per loop

为什么?如何以优雅高效的方式从列表中删除项目是否存在?

编辑:人们提到原因是list.remove在找到元素时停止,而列表理解遍历所有元素,因此,它应该更慢。

所以我尝试删除列表中的最后一个元素elt = lst[-1],以便两个进程都到达列表的最后:

In [7]: %timeit [x for x in lst if x != elt]
1000 loops, best of 3: 343 µs per loop

In [8]: %timeit lst[:].remove(elt)
10000 loops, best of 3: 143 µs per loop

为什么list.remove仍然比列表理解更快?大约快两倍。

PS:我仍然喜欢以优雅高效的方式删除列表中的元素而不关心其实际成员资格的建议。

1 个答案:

答案 0 :(得分:4)

正如评论中所提到的,无论列表的内容是什么,您的列表理解都是O(n),而remove将迭代列表,直到第一个元素出现然后将中断。所以这取决于你想要删除的元素的位置。

remove更快的第二个原因是它在C中实现,解释器在调用魔术方法__eq__时有开销,而C代码调用C函数({{1} })。

您可以在此处查看源代码:

https://svn.python.org/projects/python/trunk/Objects/listobject.c

搜索PyObject_RichCompareBool