Поиск по сайту:

Как очистить список в Python. Почему очистка списка удаляет его копии в других переменных


Почему очистка списка в Python приводит к удалению его копий в других переменных

Очистку списка в Python можно выполнить несколькими способами, некоторые из которых могут привести к неожиданным результатам, если вы не знаете различий и того, что происходит под капотом.

Давайте посмотрим на очень простой скрипт, который не делает ничего значимого, но продемонстрирует, что я имею в виду:


temp_list = list()
dict_config = dict()

for l in ['a', 'b', 'c']:
	for n in range(1,4):
		temp_list.append(l + str(n))
	dict_config[l] = temp_list
	temp_list.clear()

print(dict_config)

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

Какой результат вы ожидаете?

По замыслу автора скрипта, в результате должен получиться словарь следующего содержания:


{'a': ['a1', 'a2', 'a3'], 'b': ['b1', 'b2', 'b3'], 'c': ['c1', 'c2', 'c3']}

Но что же на самом деле получается при выполнении скрипта?

Полученный результат:


{'a': [], 'b': [], 'c': []}

То есть словарь действительно создан, ключи у него есть, но значения (которые должны были быть временными списками) пусты.

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

Логической ошибки в скрипте нет — проблема в способе очистки списка.

Как очистить список в Python

Списки в Python можно очищать несколькими способами, что приводит к 2 возможным вариантам:

1) Один из методов работает «на месте», то есть очищает те ячейки памяти, в которых хранится содержимое списка). Даже после того, как список сохранен в словаре как значение, словарь сохраняет не дубликат информации из списка, а ссылку на область памяти, где расположен список. Это приводит к тому, что если список очищается, то он очищается и в словаре, так как это не дублирующиеся данные, а всего лишь ссылка на область памяти, в которой теперь ничего нет.

2) Второй метод очистки просто создает новый объект списка и присваивает его одноименной переменной (той же переменной). При использовании этого метода очистки список, ранее сохраненный в словаре, не затрагивается.

Рассмотрим тот же скрипт, в котором строка


temp_list.clear()

заменяется строкой:


temp_list = []

То есть в качестве метода очистки выбирается присвоение нового пустого значения.


temp_list = list()
dict_config = dict()

for l in ['a', 'b', 'c']:
	for n in range(1,4):
		temp_list.append(l + str(n))
	dict_config[l] = temp_list
	temp_list = []

print(dict_config)

В этом случае скрипт будет работать как положено.

Очистка списка на месте и создание нового списка (повторная инициализация)

Итак, существуют следующие способы очистки списка «на месте»:


temp_list.clear()

del temp_list[:]

temp_list*=0

При использовании этих способов очистки списка очищаются области памяти, в которых хранится список, а также очищаются копии списка, являющиеся ссылками на эту область памяти.

И есть один способ удалить список с помощью повторной инициализации:


temp_list = []

Повторное создание списка с тем же именем не приводит к потере копий списка, хранящихся в других переменных.