与其他人提到的一样,pop 和 del 是 删除给定索引项的有效方法。然而只是为了完成(因为在 Python 中可以通过多种方式完成同样的事情):
使用切片(这不会从原始列表中删除项目):
(这也是使用 Python 列表时效率最低的方法,但在使用不支持 pop 的用户定义对象时,这可能很有用(但效率不高,我重申),但确实定义了 __getitem__ ):
>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index
>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]
注意:请注意,此方法不会像pop 和del 那样修改列表。相反,它制作了两个列表副本(一个从开始到索引但没有它(a[:index]),一个在索引之后直到最后一个元素(a[index+1:]))并通过添加两者来创建一个新的列表对象。然后将其重新分配给列表变量 (a)。旧的列表对象因此被取消引用并因此被垃圾收集(假设原始列表对象没有被除 a 之外的任何变量引用)。
这使得这种方法效率非常低,并且还会产生不良的副作用(尤其是当其他变量指向未修改的原始列表对象时)。
感谢@MarkDickinson 指出这一点...
ThisStack Overflow 回答解释了切片的概念。
另请注意,这只适用于正指数。
在与对象一起使用时,必须定义 __getitem__ 方法,更重要的是,必须定义 __add__ 方法以返回包含两个操作数中的项目的对象。
本质上,这适用于类定义如下的任何对象:
class foo(object):
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return foo(self.items[index])
def __add__(self, right):
return foo( self.items + right.items )
这适用于定义__getitem__ 和__add__ 方法的list。
三种方式在效率方面的比较:
假设以下是预定义的:
a = range(10)
index = 3
del object[index] 方法:
迄今为止最有效的方法。它适用于所有定义 __del__ 方法的对象。
反汇编如下:
代码:
def del_method():
global a
global index
del a[index]
反汇编:
10 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 DELETE_SUBSCR # This is the line that deletes the item
7 LOAD_CONST 0 (None)
10 RETURN_VALUE
None
pop 方法:
它比del方法效率低,在需要获取已删除项时使用。
代码:
def pop_method():
global a
global index
a.pop(index)
反汇编:
17 0 LOAD_GLOBAL 0 (a)
3 LOAD_ATTR 1 (pop)
6 LOAD_GLOBAL 2 (index)
9 CALL_FUNCTION 1
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
切片和添加方法。
效率最低的。
代码:
def slice_method():
global a
global index
a = a[:index] + a[index+1:]
反汇编:
24 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 SLICE+2
7 LOAD_GLOBAL 0 (a)
10 LOAD_GLOBAL 1 (index)
13 LOAD_CONST 1 (1)
16 BINARY_ADD
17 SLICE+1
18 BINARY_ADD
19 STORE_GLOBAL 0 (a)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
None
注意:在所有三个反汇编中,忽略最后两行基本上是return None。此外,前两行正在加载全局值 a 和 index。