Python: ссылки или значения?
Как вы думаете, что происходит, когда вы пишете следующее выражение?
a = b
Логичным, однако не совсем корректным ответом, будет "переменной a присваивается значение b". Простой пример:
first = [1, 2, 3] second = first second[0] = 5 # first = [5, 2, 3]
Если бы second просто присваивалось значение first, то при изменении second first не менялась бы. Однако это произошло. Cуть в том, что в python все объекты передаются по ссылке(а это объекты класса list). То есть для python всё равно, что вы напишете - first или second - они указывают на одну область в памяти и изменения, сделанные в значении одной переменной, отобразятся и во второй. Однако надо понимать разницу между изменением и присвоением ей нового значения:
first = [1, 2, 3] second = first second = [2, 3, 4] # first не изменился
После присвоения second значения [2, 3, 4] эта переменная теперь указывает на новую область памяти и уже никак не связана с first.
Абсолютно тот же механизм использует передача аргументов в функцию:
def change_value(value): value[0] = 10 value = [3, 4, 5] a = [1, 2, 3] change_value(a) # a = [10, 2, 3]
Первая строчка в функции изменяет значение в памяти, а вторая создаёт ссылку на новую область памяти, а значит связь value с a теряется.
Понимание этого механизма может облегчить вам жизнь при работе с данными в Python.
Например может показаться, что следующий код создаёт двумерный список 3 на 3, заполненный нулями
a = [[0] * 3] * 3 # a = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Однако это не совсем тот список, который мы ожидаем увидеть: список [0, 0, 0] передаётся по ссылке, а значит все три вложенных списка указывают на одну область памяти.
a[0][0] = 1 # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
Нетрудно заметить, что изменились все 3 списка, то есть толку от них мало. "Правильным" созданием такого списка было бы
a = [[0] * 3 for _ in range(3)]
В этом выражении, каждый новый элемент - новая область в памяти, а значит вложенные списки независимы:
a[0][0] = 1 # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
Надеюсь, теперь вы разобрались в этой теме и не будете совершать ошибок, как в примере с массивом.
Подписывайтесь на группу SnakeBlog