Как и другие упомянутых попы и дель являются этими эффективными способами удаления элемента из данного индекса. Тем не менее, просто для завершения (поскольку то же самое можно сделать разными способами в Python):
Использование срезов (это не означает удаление элемента из исходного списка):
(Также это будет наименее эффективный метод при работе со списком Python, но это может быть полезно (но неэффективно, я повторяю) при работе с пользовательскими объектами, которые не поддерживают pop, но все же определяют a __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 за указание на это ...
Этот ответ переполнения стека объясняет концепцию нарезки.
Также обратите внимание, что это работает только с положительными показателями.
При использовании с объектами __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 )
Это работает с list
которой определяет __getitem__
и __add__
методы.
Сравнение трех способов с точки зрения эффективности:
Предположим, что предопределено следующее:
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
.
O(n)
во времени.deque()
обеспечивает эффективные операции на обоих концах, но не обеспечивает O (1) вставок / поисков / удалений в середине.