Подтвердить что ты не робот

Различные способы удаления списков

Я хочу понять, почему:

  • a = [];
  • del a; и
  • del a[:];

ведут себя по-другому.

Я провел тест для каждого, чтобы проиллюстрировать различия, которые я видел:

>>> # Test 1: Reset with a = []
... 
>>> a = [1,2,3]
>>> b = a
>>> a = []
>>> a
[]
>>> b
[1, 2, 3]
>>> 
>>> # Test 2: Reset with del a
... 
>>> a = [1,2,3]
>>> b = a
>>> del a
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
[1, 2, 3]
>>> 
>>> # Test 3: Reset with del a[:]
... 
>>> a = [1,2,3]
>>> b = a
>>> del a[:]
>>> a
[]
>>> b
[]

Я нашел Различные способы очистки списков, но я не нашел объяснения различий в поведении. Может ли это объяснить это?

4b9b3361

Ответ 1

Тест 1

>>> a = [1,2,3] # set a to point to a list [1, 2, 3]
>>> b = a # set b to what a is currently pointing at
>>> a = [] # now you set a to point to an empty list

# Step 1: A --> [1 2 3]

# Step 2: A --> [1 2 3] <-- B

# Step 3: A --> [     ] [1 2 3] <-- B

# at this point a points to a new empty list
# whereas b points to the original list of a

Тест 2

>>> a = [1,2,3] # set a to point to a list [1, 2, 3]
>>> b = a # set b to what a is currently pointing at
>>> del a # delete the reference from a to the list

# Step 1: A --> [1 2 3]

# Step 2: A --> [1 2 3] <-- B

# Step 3:       [1 2 3] <-- B

# so a no longer exists because the reference
# was destroyed but b is not affected because
# b still points to the original list

Тест 3

>>> a = [1,2,3] # set a to point to a list [1, 2, 3]
>>> b = a # set b to what a is currently pointing at
>>> del a[:] # delete the contents of the original

# Step 1: A --> [1 2 3]

# Step 2: A --> [1 2 3] <-- B

# Step 2: A --> [     ] <-- B

# both a and b are empty because they were pointing 
# to the same list whose elements were just removed  

Ответ 2

Из трех "способов удаления списков Python" только один фактически изменяет исходный объект списка; другие два влияют только на имя.

  • a = [] создает новый объект списка и присваивает ему имя a.
  • del a удаляет имя, не объект, на который он ссылается.
  • del a[:] удаляет все ссылки из списка, на который ссылается имя a (хотя, аналогично, оно не влияет непосредственно на объекты, на которые ссылаются в списке).

Возможно, стоит прочитать эту статью о именах и значениях Python, чтобы лучше понять, что здесь происходит.

Ответ 3

Test 1: восстанавливает a к новому объекту, b все еще содержит ссылку на исходный объект, a - это просто имя, перебирая a на новый объект, не меняет оригинальный объект, который b указывает на.

Test 2: укажите имя a, чтобы он больше не существовал, но снова вы все еще имеете ссылку на объект в памяти с помощью b.

Test 3 a[:] точно так же, как при копировании списка или изменении всех элементов списка ссылается на ссылки на объекты, хранящиеся в списке, а не на имя a. b также очищается, так как снова это ссылка на a, поэтому изменения в содержании a будут влиять на b.

Поведение документировано:

Существует способ удалить элемент из списка с учетом его индекса его значения: оператор del. Это отличается от pop()метод, который возвращает значение. Оператор del также может использоваться для удалить фрагменты из списка или очистить весь список (что мы сделали ранее назначением пустого списка на срез). Например:

>>>
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]

del также может использоваться для удаления целых переменных:

>>>
>>> del a

Ссылка на имя a в дальнейшем будет ошибкой (по крайней мере до другой ему присваивается значение). Мы найдем другие варианты использования del позже.

Таким образом, только del a на самом деле удаляет a, a = [] выполняет переподключение a к новому объекту и del a[:] очищает a. В вашем втором тесте, если b не содержал ссылку на объект, он собирал мусор.

Ответ 4

del a

удаляет переменную a из области видимости. Цитирование из python docs:

Удаление имени удаляет привязку этого имени из локального или глобальное пространство имен, в зависимости от того, происходит ли это имя в глобальной в том же блоке кода.

del a[:]

просто удаляет содержимое a, так как удаление передается объекту a, а не применяется к нему. Опять из документов:

Удаляются ссылки на атрибуты, подписки и слайсы к основному объекту; удаление разреза в целом эквивалентно присвоению пустого фрагмента правильного типа (но даже это определяется срезанным объектом).

.

Ответ 5

Из этих трех методов только третий метод фактически приводит к удалению списка, на который указывает 'a'. Давайте сделаем краткий обзор.

Когда вы правы a = [1, 2, 3], он создает список в памяти с элементами [1, 2, 3], а затем получает "a", чтобы указать на него. Когда вы пишете b = a, эта преформа означает, что "называется" мелкой копией ", то есть она указывает" b "на тот же блок памяти, что и" a ". глубокая копия предполагает копирование содержимого списка в новый блок памяти, а затем указание на это.

теперь, когда вы пишете a = [], вы создаете новый список без элементов в нем и получаете 'a', чтобы указать на него. исходный список все еще существует, и 'b' указывает на него.

во втором случае del a удаляет указатель на [1,2,3], а не сам массив. это означает, что b может указывать на него.

Наконец, del a[:] проходит через данные, которые 'a' указывает и опустошает его содержимое. 'a' все еще существует, поэтому вы можете использовать его. 'b' также существует, но он указывает на один и тот же пустой список 'a', поэтому он дает тот же результат.

Ответ 6

Чтобы понять разницу между различными способами удаления списков, давайте посмотрим каждый из них один за другим с помощью изображений.

>>> a1 = [1,2,3]

Новый объект списка создается и назначается a1.

i1

>>> a2 = a1

Мы присваиваем a1 a2. Итак, список a2 теперь указывает на объект списка, к которому указывает a1.

i2

РАЗЛИЧНЫЕ МЕТОДЫ, РАЗРАБОТАННЫЕ НИЖЕ:

Метод-1 Использование []:

>>> a1 = []

i3

При назначении пустого списка a1 на a2 не влияет. a2 по-прежнему относится к одному и тому же объекту списка, но a1 теперь относится к пустым спискам.

Метод-2 Используя del [:]

>>> del a1[:]

i4

Это удаляет все содержимое объекта списка, на который указывал a1. a1 теперь указывает на пустой список. Поскольку a2 также ссылался на один и тот же объект списка, он также становится пустым.

Метод-3 Использование del a1

>>> del a1
>>> a1
NameError: name 'a1' is not defined

i5

Это удаляет переменную a1 из области действия. Здесь удаляется только переменная a1, исходный список все еще присутствует в памяти. a2 все еще указывает на тот исходный список, на который указывает a1. Если мы попытаемся получить доступ к a1, мы получим NameError.