首页 > 解决方案 > Python分配给切片vs从末尾删除?

问题描述

想象一下,我们想要创建所有长度为 5 的列表,这些列表[0, -1]以 3 个整数开始和结束,这些整数都是 2 或 3。一个这样的列表(8 个可能的列表)是[0, -1, 2, 2, 3]. 这是一些简单的(错误的)递归代码:

def op(a):
    print(a)
    if(len(a) < 5):
        a.append(2)
        op(a)
        print("pre 2", a)
        a = a[:-1] #.pop()
        print("post 2", a)
    if(len(a) < 5):
        a.append(3)
        print("pre 3", a)
        op(a)
        print("post 3", a)
        a = a[:-1] #.pop()

op(a)
print(a)

但是,此代码不起作用并输出一些随机列表。但是,如果我们用 替换该行a = a[:-1]a.pop()它完全可以正常工作。为什么有区别?

标签: pythonlistrecursionslice

解决方案


  • a = a[:-1]创建一个新的列表对象并将其重新绑定到 name a。所有引用该名称的先前堆栈条目a都将引用原始的、未截断的列表。
  • a.pop()执行删除最后一个元素的就地操作。它不会改变名称a所指的内容。所有堆栈条目都将引用截断列表。

在不重新绑定名称的情况下删除最后一个元素的其他方法是

  • a[:] = a[:-1]. 这将获取新列表并将a[:-1]其分配. a请记住,表单a[x] = y调用的任何表达式type(a).__setitem__(a, x, y),这通常是对 的就地操作a,同时完全a = x重新绑定名称a
  • del a[-1]. 这相当于调用type(a).__delitem__(a, -1). 同样,就地操作非常类似于pop除了它不返回元素。
  • a[-1:] = []. 这有点像 的倒数a[:] = a[:-1]。与其作为要保留的所有元素的切片辞职,不如将空分配给要删除的切片。

推荐阅读