5.6. Вложенные списки и глубокое копированиеВ этом разделе рассматривается еще одна нетривиальная тема, которую можно пропустить, если вы только изучаете язык.
Как упоминалось ранее, списки могут содержать вложенные списки. В частности, вложение списков может использоваться для представления двумерных матриц. К элементам этих матриц можно обращаться по двумерным индексам. Индексы матриц работают так:
>>> m = [[0, 1, 2], [10, 11, 12], [20, 21, 22]]
>>> m[0]
[0, 1, 2]
>>> m[0][1]
1
>>> m[2]
[20, 21, 22]
>>> m[2][2]
22
Этот механизм естественным образом масштабируется для большего количества измерений.
В большинстве случаев ни о чем больше вам беспокоиться не придется. Однако у вас могут возникнуть проблемы с вложенными списками — они возникают из-за того, как переменные связываются с объектами, и из-за возможности изменения некоторых объектов (например, списков). Следующий пример демонстрирует эти проблемы:
>>> nested = [0]
>>> original = [nested, 1]
>>> original
[[0], 1]
Рисунок 5.1 поясняет суть происходящего. Теперь зна-чение во вложенном списке можно изменить как через переменную nested , так и через original :
>>> nested[0] = 'zero' 
>>> original
[['zero'], 1] Рис. 5.1. Список, первый
>>> original[0][0] = 0 элемент которого ссылается
>>> nested на вложенный список
>>> original
[[0], 1]
Но если присвоить nested другой список, связь между списками будет разорвана: >>> nested = [2]
>>> original
[[0], 1]
Эта ситуация изображена на рис. 5.2.
Вы уже видели, что для создания копии списка можно воспользоваться полным сегментом (то есть x[:] ). Также копию списка можно получить при помощи опе-ратора + или * (например, x + [] или x * 1 ). Эти способы несколько уступают по эффективности способу с сег-ментом. Все три способа создают поверхностную копию списка — вероятно, в большинстве случаев это именно то, что вам нужно. Но если ваш список содержит другие
вложенные списки, возможно, вы предпочтете создать Рис. 5.2. Первый элемент глубокую копию. Для этого можно воспользоваться исходного списка все ещефункцией deepcopy модуля copy : остается вложенным списком,>>> original = [[0], 1] ссылается на другой список но переменная nested>>> shallow = original[:]
>>> import copy
>>> deep = copy.deepcopy(original)
Рисунок 5.3 поясняет суть глубокого копирования.
Списки, на которые указывают переменные original или shallow, связаны. Изме-нение значения во вложенном списке через одну переменную повлияет на другую переменную:
>>> shallow[1] = 2
>>> shallow
[[0], 2]
>>> original
[[0], 1]
>>> shallow[0][0] = 'zero'
>>> original
[['zero'], 1]
Глубокая копия не зависит от оригинала, и из-
менения в ней не отражаются на исходном
списке:
>>> deep[0][0] = 5 
>>> deep
[[5], 1] Рис. 5.3. При поверхностном
>>> original копировании не копируются
[['zero'], 1] вложенные списки
Это поведение присуще всем остальным вложенным объектам в изменяемых спи-сках (например, словарях).
Итак, теперь вы знаете, что можно сделать при помощи списков, и мы можем об-ратиться к кортежам.
ПОПРОБУЙТЕ.САМИ:.КОПИРОВАНИЕ.СПИСКОВ Имеется следующий список: x = [[1, 2,3], [4, 5, 6], [7, 8, 9]] . Какой код вы бы использовали для создания копии y этого списка, в которой элементы можно было бы изменять без побочного эффекта с изменением содержимого x ?
5.7. Кортежи
Кортеж как структура данных очень похож на список, но кортежи не могут из-меняться; их можно только создавать. Кортежи настолько похожи на списки, что у вас даже может возникнуть вопрос, для чего они были включены в Python. Дело в том, что у кортежей есть важные роли, которые не могут эффективно выполняться списками (например, роль ключей в словарях).
5.7.1. Знакомство с кортежами
Создание кортежа практически не отличается от создания списка: переменной присваивается последовательность значений. Список представляет собой последо-вательность, заключенную в квадратные скобки [ и ] ; кортеж представляет собой последовательность, заключенную в круглые скобки ( и ) : >>> x = ('a', 'b', 'c')
Эта строка создает кортеж из трех элементов.
После того как кортеж будет создан, операции с ним очень похожи на операции со списками — настолько, что разработчику легко забыть, что кортежи и списки являются разными типами данных:
Читать дальше