zaLinux.ru

Как очистить список в 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) Один из способов действует «на месте» (in-place), то есть очищает те ячейки памяти, в которых хранится содержимое списка). Даже после того, когда список сохранён в словарь в качестве значения, в словаре хранится не дубликат информации из списка, а ссылка на область памяти, где размещён список. Это приводит к тому, что если список очищен, то он также очищается и в словаре, поскольку это не дублированные данные, а всего лишь ссылка на область памяти, в которой теперь ничего нет.

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)

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

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

Итак, имеются следующие способы очистить список«на месте» (in-place):


temp_list.clear()

del temp_list[:]

temp_list*=0

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

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

temp_list = []

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


Рекомендуемые статьи:

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *