【问题标题】:Difference between list.pop() and list = list[:-1]list.pop() 和 list = list[:-1] 的区别
【发布时间】:2020-05-13 23:53:40
【问题描述】:
>>> a = [1,2,3]
>>> a.pop()
3
>>> a
[1, 2]
>>> a = [1,2,3]
>>> a = a[:-1]
>>> a
[1, 2]
>>>

上述从列​​表中删除最后一个元素的方法有什么区别吗?

【问题讨论】:

  • 是的,使用 pop 会在常量 timw 中就地修改 a 引用的列表,而使用切片会创建一个新列表并将其分配给 a 并以线性时间工作

标签: python list


【解决方案1】:

是的。 pop 是 O(1) 并改变原始列表,而 slice 是 O(n) 并创建列表的副本。不太正式,pop 方法是对列表末尾元素的操作,在 CPython 中定义为对list_resize(self, Py_SIZE(self) - 1); 的调用。这不会遍历整个结构。

另一方面,list_slice 分配一个新列表并循环遍历旧列表中从头到尾的条目 - 1,将对每个项目的引用复制到新列表中。

如果您要删除列表的最后一个元素,请使用popdel a[-1]

【讨论】:

  • pop可以接受一个索引参数,比如pop(0),这种情况下还是O(1)吗?
  • 好问题。否--pop 传统上是对堆栈数据结构的“顶部”或后/右的 O(1) 操作。 Python 中的列表为pop 提供了一个额外参数以使其能够在中间工作,但列表中的其余元素需要向前移动以填补空白,O(n)。查看完整故事的源代码。有一个条件可以在pop()pop(n) 之间切换——后者调用list_ass_slice(self, index, index+1, (PyObject *)NULL);,它对列表执行前移操作。如果您经常使用pop(0),请查看collections.deque
  • 实际上,如果您只想删除list 的最后一个元素,那么del mylist[-1] 是可行的方法。当您想从list 中删除最后一个元素并保留该值(pop 返回)时,您可以使用popdel mylist[-1]pop 具有相同的大 O 行为,并且它直接支持语法/字节码,这通常比函数调用更快(尽管现代版本的 CPython 通过加快简单的方法调用来缩小差距)。跨度>
【解决方案2】:

pop 不改变id,只弹出列表中的一项。

[:-1] 是切片操作,从旧列表中创建一个新列表。

>>> a = [1,2,3]
print(id(a))
>>> a.pop()
3
print(id(a))
>>> a
[1, 2]
>>> a = [1,2,3]
>>> a = a[:-1]
>>> a
print(id(a))
[1, 2]
>>>

id输出(数字不重要,相同或不同是关键):

4470627464
4470627464
4474450952

【讨论】:

  • 值得注意的是,因为pop 改变了a 引用的列表,而切片操作更新a 以引用一个新列表,所以当一些其他变量引用相同的列表
【解决方案3】:

pop 方法从列表中返回它删除的最后一项。 例如:

a = [1,2,3,4]
b = a.pop()
print(b)  # 4

此外,使用切片,您正在制作旧列表的副本,而使用 pop 时,列表引用保持不变。

【讨论】:

    【解决方案4】:

    使用 in 函数有一个基本的区别。使用[:-1] 未更改原始列表,但pop() 可以。

    a = [1,2,3]
    b = [1,2,3]
    
    
    def functionb(list):
        list = list[:-1]
        return list
    def withpop(list):
        return list.pop()
    
    functionb(b)
    withpop(a)
    print b
    print a
    

    将打印:

    [1, 2, 3]
    [1, 2]
    

    其次是执行时间。 pop()[:-1] 快,因为当您使用 [:-1] 时,您必须覆盖到列表。假设您在索引中有数千个值,所以它会比 pop()

    【讨论】:

      【解决方案5】:

      你呈现它们的方式,没有外在的区别。 pop 指令使解释器更容易优化指令,因为它只能减少列表的长度属性。 -1 分配将构造一个新列表,将其分配给 a,然后将旧列表留给垃圾回收。

      别名有很大的不同:如果您为该列表分配了其他内容,您将获得pop 的副作用。例如:

      >>> a = [1, 2, 3, 4]
      >>> b = a
      >>> b
      [1, 2, 3, 4]
      >>> a.pop()
      4
      >>> b
      [1, 2, 3]
      >>> a = a[:-1]
      >>> b
      [1, 2, 3]
      >>> a
      [1, 2]
      

      【讨论】:

      • 请注意,如果需要,切片也可以执行相同的副作用,方法是将 a = a[:-1] 更改为 a[:] = a[:-1];而不是将a 重新绑定到新的list,而是分配给“空”切片,用切片的结果替换原始list内容
      【解决方案6】:

      是的,有区别。 当您使用 a.pop() 时,您也会从列表中删除 当您使用 [:-1] 对象列表时不会改变 检查 len(a)

      >>> a = [1,2,3]
      >>> a
      [1, 2, 3]
      >>> a[:-1]
      [1, 2]
      >>> len(a[:-1])
      2
      >>> a.pop()
      3
      >>> a
      [1, 2]
      >>> len(a)
      2
      >>> 
      

      【讨论】:

        猜你喜欢
        • 2010-10-15
        • 2011-04-07
        • 2012-09-26
        • 2023-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-08
        • 1970-01-01
        相关资源
        最近更新 更多