Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 按索引删除列表元素是否比按值删除更有效?_Python_Performance_Runtime_Python Internals - Fatal编程技术网

Python 按索引删除列表元素是否比按值删除更有效?

Python 按索引删除列表元素是否比按值删除更有效?,python,performance,runtime,python-internals,Python,Performance,Runtime,Python Internals,在python中,假设我们有以下列表: my_list=['a','b','c','d',…] my\u list.pop(3)会比my\u list.remove('d')更有效吗?对于小列表来说没有多大关系: [wander@box ~]$ python -m timeit '[1, 2, 3].pop(1)' 10000000 loops, best of 3: 0.167 usec per loop [wander@box ~]$ python -m timeit '[1, 2, 3].

在python中,假设我们有以下列表:
my_list=['a','b','c','d',…]


my\u list.pop(3)
会比
my\u list.remove('d')更有效吗?

对于小列表来说没有多大关系:

[wander@box ~]$ python -m timeit '[1, 2, 3].pop(1)'
10000000 loops, best of 3: 0.167 usec per loop
[wander@box ~]$ python -m timeit '[1, 2, 3].remove(2)'
10000000 loops, best of 3: 0.129 usec per loop
如果您的列表非常大,或者比较列表中的元素需要很长时间,那么可能会有更大的差异。删除将较慢,因为它必须通过(并比较)所有元素:

[wander@box ~]$ python -m timeit -n 100000 'list(range(1, 100)).pop(98)'
100000 loops, best of 3: 0.916 usec per loop
[wander@box ~]$ python -m timeit -n 100000 'list(range(1, 100)).remove(98)'
100000 loops, best of 3: 2.05 usec per loop
这就是整数,比较起来很快。如果列表中的元素具有更有趣的
\uuuu eq\uuu
方法,
删除
可能需要很长时间:

class Foo:
    def __eq__(self, other):
        time.sleep(1)
        return False

[Foo(), Foo(), Foo(), Foo(), 20].remove(20)

因此,如果您知道索引,请使用
pop

对于小列表来说没有多大关系:

[wander@box ~]$ python -m timeit '[1, 2, 3].pop(1)'
10000000 loops, best of 3: 0.167 usec per loop
[wander@box ~]$ python -m timeit '[1, 2, 3].remove(2)'
10000000 loops, best of 3: 0.129 usec per loop
如果您的列表非常大,或者比较列表中的元素需要很长时间,那么可能会有更大的差异。删除将较慢,因为它必须通过(并比较)所有元素:

[wander@box ~]$ python -m timeit -n 100000 'list(range(1, 100)).pop(98)'
100000 loops, best of 3: 0.916 usec per loop
[wander@box ~]$ python -m timeit -n 100000 'list(range(1, 100)).remove(98)'
100000 loops, best of 3: 2.05 usec per loop
这就是整数,比较起来很快。如果列表中的元素具有更有趣的
\uuuu eq\uuu
方法,
删除
可能需要很长时间:

class Foo:
    def __eq__(self, other):
        time.sleep(1)
        return False

[Foo(), Foo(), Foo(), Foo(), 20].remove(20)
因此,如果您知道索引,请使用
pop

根据,这两种方法的复杂性是:

pop     O(n - i)
remove  O(n)
使用列表长度
n
和元素的索引
i

因此,根据列表的大小,
pop
从长远来看可能会更快。

根据,这两种方法的复杂性是:

pop     O(n - i)
remove  O(n)
使用列表长度
n
和元素的索引
i


因此,根据列表的大小,从长远来看,
pop
可能会更快。

查看和的实际C代码(您指的是CPython,对吧?),您可以看到:

  • .remove
    需要迭代列表(因此按
    O(i)
    进行缩放,其中
    i
    是项目的索引)

  • .pop
    采用快捷方式,如下所示:

    • 判断索引是否超出范围(第928行)很简单,但是
      .remove
      必须检查整个列表以找到它的目标(或者不这样做);及

    • 在特殊情况下,索引是列表中的最后一项(第933行)

  • listremove
    调用了
    PyObject\u richcomarebool
    (第2200行),这相对比较昂贵,因为它需要检查当前索引中的对象是否等于该项;及

  • 一旦找到合适的切片位置,这两个(除了上面提到的
    .pop
    的特殊情况)最终都会委托(第941行和第2202行-后面没有咯咯笑);这必须将数组其余部分中的项洗牌,因此将
    O(n-i)

  • 在此基础上,
    .pop
    将更快,尤其是对于列表中的最后一项;但是,如果您从项目本身开始,并且已经进行了
    O(n)
    操作,并进行了丰富的比较,以查找其
    .index
    ,那么您在回旋处失去的摆动中获得了什么

    此外,重新排列数组中剩余的所有内容(即
    列表\u ass\u slice
    )以弥补您删除的内容的操作,
    .pop
    .remove
    都需要执行,这可能比首先确定要删除的项目要昂贵得多


    请注意,在不深入源代码的情况下,只要从逻辑上考虑每个操作所涉及的内容,几乎可以解决上述所有问题。

    查看实际的C代码(您指的是CPython,对吧?),您可以看到:

  • .remove
    需要迭代列表(因此按
    O(i)
    进行缩放,其中
    i
    是项目的索引)

  • .pop
    采用快捷方式,如下所示:

    • 判断索引是否超出范围(第928行)很简单,但是
      .remove
      必须检查整个列表以找到它的目标(或者不这样做);及

    • 在特殊情况下,索引是列表中的最后一项(第933行)

  • listremove
    调用了
    PyObject\u richcomarebool
    (第2200行),这相对比较昂贵,因为它需要检查当前索引中的对象是否等于该项;及

  • 一旦找到合适的切片位置,这两个(除了上面提到的
    .pop
    的特殊情况)最终都会委托(第941行和第2202行-后面没有咯咯笑);这必须将数组其余部分中的项洗牌,因此将
    O(n-i)

  • 在此基础上,
    .pop
    将更快,尤其是对于列表中的最后一项;但是,如果您从项目本身开始,并且已经进行了
    O(n)
    操作,并进行了丰富的比较,以查找其
    .index
    ,那么您在回旋处失去的摆动中获得了什么

    此外,重新排列数组中剩余的所有内容(即
    列表\u ass\u slice
    )以弥补您删除的内容的操作,
    .pop
    .remove
    都需要执行,这可能比首先确定要删除的项目要昂贵得多


    请注意,在不深入源代码的情况下,只要从逻辑上考虑每个操作所涉及的内容,几乎可以解决上述所有问题。

    您是否尝试过使用
    timeit
    对其进行计时?仅仅因为在某些任意输入下,某些功能会更好,并不意味着它更高效。我在寻找一个更具理论性的答案。它们不是等价的——你已经知道索引或项目了吗?我希望将数组中的所有其他内容都移动到d