Передача по назначению: Python

#python #pass-by-reference #variable-assignment

#python #передача по ссылке #переменная-назначение

Вопрос:

Я хотел разобраться в следующих вариантах кода:

 a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print(a, b)
  

Насколько я понял, эта переменная a ссылается на объект, который содержит список [1,2,3] в некотором месте в памяти, и b теперь ссылается на тот же объект, на который a ссылается, и по этой ссылке мы технически добавляем a, а не b.

Вывод: [1, 2, 3, 4] ['a', 'b']

Я немного обновил код:

 a = [1, 2, 3]
b = ['a', 'b']
b = a
b.append(4)
print(a, b)
  

Насколько я понимаю: b теперь ссылается на два объекта, первый список ['a','b'] и второй список (на который a изначально ссылается) [1,2,3] через третью строку b = a .

Вывод: [1, 2, 3, 4] [1, 2, 3, 4]

Последний вариант кода:

 a = [1, 2, 3]
b = ['a', 'b']
b = a
b.append(4)
a.append(10)
print(a, b)
  

исходя из моего понимания на данный момент, я подумал, что ссылка в строке 3 b = a предоставляла только b возможность ссылаться на несколько объектов (своих и a ‘s) и a должна была ссылаться только на один объект [1,2,3] , поэтому ожидаемый результат должен быть: [1,2,3,4,10] [1,2,3,4]

Фактический результат: [1, 2, 3, 4, 10] [1, 2, 3, 4, 10]

Итак, это назначение в строке 3 b = a похоже на двунаправленную ссылку? где также создается ссылка на объект a на b ?

Я надеюсь, что кто-нибудь сможет прояснить для меня эту путаницу и поправить меня в моих мыслях, если я был неправ. Спасибо.

Комментарии:

1. переменная a и переменная b ссылаются на один и тот же список . если вы измените один из них, другой также получит эти изменения. Если вы хотите скопировать список, используйте new_list = list.copy() Это также может помочь: programiz.com/python-programming/methods/list/copy

2. Почему вы делаете это таким сложным? После того, как b = a , a и b являются одним и тем же объектом, это все, что от него требуется.

3. «технически мы добавляем в a, а не в b». нет. Переменные ссылаются на объекты. Обе переменные ссылаются на один и тот же объект, и вы добавляете их к этому объекту . Вы не добавляете к переменной. «Насколько я понимаю: b теперь ссылается на два объекта» Ну, не одновременно . Вначале он ссылается на один объект, а позже ссылается на другой. Прочитайте следующее: nedbatchelder.com/text/names.html

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

5. «исходя из моего понимания до сих пор, я думал, что ссылка в строке 3 b = a давала только b возможность ссылаться на несколько объектов (своих и a ) и » нет. переменные могут ссылаться только на один объект за раз . Я думаю, это то, что вас смущает.

Ответ №1:

Насколько я понимаю: b теперь ссылается на два объекта, . . .

Это неверно. Имя не может быть связано с несколькими объектами в заданной области одновременно.

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

Ответ №2:

Не думайте об объектах как о указателях, я думаю, что это источник вашей путаницы. Дело не в том, что «b указывает на a» или «a указывает на b», это связано с привязкой к объекту. Я думаю, что просмотр id будет полезен

 >>> a = [1, 2, 3]
>>> id(a)
1833964774216
>>> b = a
>>> id(b)
1833964774216
  

В этом случае оба a и b привязаны к этому списку. Таким образом, любая мутация в list 1833964774216 будет отражена в обоих объектах. Но я могу переназначить (или повторно привязать) к совершенно другому объекту

 >>> b = [4, 5, 6]
>>> id(b)
1833965089992
>>> b
[4, 5, 6]
  

На a это никак не влияет, потому что оно по-прежнему привязано к исходному списку

 >>> a
[1, 2, 3]
>>> id(a)
1833964774216
  

Ответ №3:

давайте поймем разницу между именами и объектами. В вашем случае a и b — это имена, а список «[1,2,3]», присвоенный a и b, является объектом. Изначально a = [1,2,3] и после того, как a присваивается b, т. е. b = a, в этом случае и a, и b привязаны к одному и тому же объекту списка. Это означает, что вы можете изменить значение этого объекта списка, используя любое из имен a или b.

Это можно преодолеть, скопировав список, присвоенный a, в b как,

b = a.copy()

который создаст копию того же объекта, назначенного b