简体   繁体   English

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

[英]Why is list.remove faster than list comprehension?

I am not fond of the following way of removing an element from a list: 我不喜欢以下从列表中删除元素的方法:

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

I know it is ok to use try except blocks in Python and I actually use them, but in this particular case I wish there was a list.remove_if_exists(elt) method when I don't really need to handle the case when the element is not in the list. 我知道在Python中使用try除了块并且我实际上使用它们是可以的,但是在这种特殊情况下我希望有一个list.remove_if_exists(elt)方法,当我不需要处理这个元素的情况时不在列表中。

To make things clearer I tried using a list comprehension: 为了使事情更清楚,我尝试使用列表理解:

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

However, this turned out to be slower: 然而,结果变慢了:

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

Why is that? 这是为什么? And how can I remove an item from a list whether it exists or not in an elegant and efficient way? 如何以优雅高效的方式从列表中删除项目是否存在?

Edit: people mentioned the reason is that list.remove stops when finding the element and the list comprehension goes through all elements, therefore, it should be slower. 编辑:人们提到原因是list.remove在找到元素时停止,列表理解遍历所有元素,因此,它应该更慢。

So I tried removing the last element in the list, elt = lst[-1] , so that both processes reach the very end of the list: 所以我尝试删除列表中的最后一个元素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

Why is list.remove still faster than the list comprehension? 为什么list.remove仍然比列表理解更快? About twice as fast. 大约快两倍。

PS: I'd still love to suggestions for elegant and efficient ways of removing an element in a list without caring about its actual membership. PS:我仍然喜欢建议优雅而有效的方法来删除列表中的元素而不关心它的实际成员资格。

As mentioned in the comments, your list comprehension is O(n) no matter what the content of the list, while remove will iterate over the list until the first element is present and then will break. 正如评论中所提到的,无论列表的内容是什么,列表理解都是O(n) ,而remove将遍历列表,直到第一个元素出现,然后才会中断。 So this depends on the position of the element you want to remove. 因此,这取决于要删除的元素的位置。

A second reason that the remove is much faster is that it's implemented in C, the interpreter has overhead of calling the magic method __eq__ while the C code calls a C function ( PyObject_RichCompareBool ). remove速度快得多的第二个原因是它在C中实现,解释器在C代码调用C函数( PyObject_RichCompareBool )时调用魔术方法__eq__开销。

You can see the source code here: 你可以在这里看到源代码:

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

Search for listremove 搜索listremove

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM