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

Допустим, у вас есть блокнот с конспектами по MAT188 или любому предмету 📓 . Твой друг просит твой блокнот. Вы соглашаетесь поделиться с ними своей записной книжкой. Есть несколько способов, которыми вы могли бы подарить свой блокнот,

  • Вы можете получить ксерокопию или фотокопию своей записной книжки и поделиться с ними копией.
  • Вы могли бы дать свой собственный блокнот

Рассмотрим случай, когда вы дали другу копию своей записной книжки. Если они должны были внести какие-либо изменения в примечания или добавить какие-либо примечания, они могли сделать это в своей копии. Ваш оригинальный блокнот не будет затронут. Однако в этом сценарии вам потребовалось некоторое время и место (2 книги вместо 1), чтобы фактически сделать копию своей записной книжки. Если все, что сделал ваш друг, это добавил одну страницу, вы прошли через все хлопоты по созданию копии почти даром.

Теперь рассмотрим второй случай. Вместо того, чтобы создать копию, вы дали свой блокнот своему Другу. В этом случае вам не нужно было тратить время на создание копии вашей книги, и есть только одна книга (копии не существует). Однако, если ваш друг внесет какие-либо изменения в ваши заметки, он должен будет сделать это в исходной записной книжке. Поэтому, когда они вернут вам ваш блокнот, в вашем блокноте также будет их сдача.

Записная книжка — это аргумент/параметр, передаваемый функции. Первый случай, когда вы передаете другу копию своей записной книжки, похож на передачу по значению, а второй случай, когда вы передаете другу свою оригинальную записную книжку, — передачу по ссылке.

Пройти по ссылке

Когда вы передаете параметр по ссылке, любые изменения, внесенные в параметр внутри функции, также отражаются вне функции.

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

Пройти по значению

Копия переменной передается в качестве параметра. Любые изменения, внесенные в этот параметр, НЕ отражаются за пределами функции.

  • Поскольку вы создаете копию своей переменной, это занимает больше времени и места.
  • Поскольку ваша исходная переменная остается неизменной, вы не «теряете» свою переменную.

Ниже приведена картинка, изображающая передачу по значению и передачу по ссылке.

Как насчет Питона?

Python не является ни передачей по ссылке, ни передачей по значению. Это довольно уникально, это передается по ссылке на объект

Ниже приведен вывод приведенного выше кода

Defined Variable a 
Variable a is located at address 9785184 
In function 
Variable x is located at address 9785184 
Variable a is located at address 9785184

id() используется для получения целочисленного представления адреса памяти переменной в Python.
Как видите, адрес памяти переменной a и параметр x тот же. Это означает, что они находятся по одному и тому же адресу. Однако это не передача по ссылке. Посмотрите на код ниже, где мы изменяем **параметр x** внутри функции.

Ниже приведен вывод приведенного выше кода

Defined Variable a 
Address of a is 9785184 
value of a is 10 
Inside Function 
Address of x is 9785184 
Modifying variable x 
Address of x is 9785504 
value of x is 20 
value of a is 10

После того, как мы изменим параметр x внутри функции, адрес памяти параметра x изменится. И, как вы можете видеть в двух последних напечатанных операторах, значения x и a различны. Однако это также не передача по значению, поскольку адреса памяти параметра x и переменной a изначально одинаковы.
Это ссылка на передачу объекта в Python. .

В Python все является объектом, а объекты либо изменяемыми, либо неизменяемыми. Чтобы узнать больше об изменчивости, обратитесь к моей статье в День 5.

  • Если объект, передаваемый в качестве параметра, является изменяемым, изменения, сделанные внутри функции, отражаются вне функции. Пример изменяемых объектов: списки, словари, наборы
  • Если объект, передаваемый в качестве параметра, является неизменяемым, изменения, сделанные внутри функционала, НЕ отражаются за пределами функции. Пример неизменяемых объектов: Int, Float, String, Tuple, Frozen Sets

Мы уже видели случай, когда мы передаем целое число в качестве параметра. Теперь мы увидим, что происходит, когда мы передаем изменяемый объект, такой как список, в качестве параметра.

original_lst is [1, 2] 
The address of original_lst is 139792761916992 
Inside function 
The address of lst is 139792761916992 
Modifying the variable lst 
The address of lst is 139792761916992 
Lst is [1, 2, 3, 4] 
The address of original_lst is 139792761916992 
original_lst is [1, 2, 3, 4]

Адрес параметра lst не меняется даже после его изменения. Кроме того, изменения, внесенные в параметр lst, отражаются вне функции в переменной original_lst.

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

original_lst is [1, 2] 
The address of original_lst is 140088994123264 
Inside function 
The address of lst is 140088994123264 
Modifying the variable lst 
The address of lst is 140088993495680 
Lst is [3, 4] 
The address of original_lst is 140088994123264 
original_lst is [1, 2]

Как видите, адрес памяти параметра lst меняется после модификации, а значения lst и original_lst различны.

Повторное назначение параметра, независимо от того, является ли он изменяемым или нет, изменит его адрес в памяти. В результате изменения не будут отражены за пределами функции.

Как передать значения по ссылке в Python?

Что делать, если вы хотите передать неизменяемое значение по ссылке? или если вы хотите, чтобы переназначение внутри функции отражалось и за пределами функции?

Мы можем использовать переназначение вне функции, чтобы имитировать передачу по ссылке.

Inside func1 
After calling func1, original_str is Original str 
Inside func1 
After calling func2, original_str is Original str.........Updating str
  • После вызова функции func1 переменная original_str остается неизменной.
  • В функции func2 мы возвращаем параметр string и переназначаем переменную original_str. Это имитирует передачу по ссылке.

Резюме

  • Когда мы передаем параметр по ссылке, любые изменения, внесенные в него внутри функции, также отражаются вне функции.
  • Когда мы передаем параметр по значению, любые изменения, внесенные в него внутри функции, НЕ отражаются вне функции.
  • Python передается по ссылке на объект
  • Если параметр является изменяемым объектом, любые изменения, внесенные в него внутри функции, отражаются вне функции.
  • Если параметр является неизменяемым объектом, любые изменения, внесенные в него внутри функции, НЕ отражаются за ее пределами.
  • Если мы переназначим параметр внутри функции, изменения НЕ будут отражены вне функции, независимо от того, является ли параметр изменяемым или неизменяемым.
  • Чтобы имитировать передачу по ссылке в Python, мы можем повторно присвоить переменной возвращаемое значение функции.

Свяжитесь со мной в LinkedIn

Недавно я начал модифицированную версию челленджа #100daysofcode. Я стараюсь каждый день писать контент, связанный с Python, наукой о данных или программированием. Следите за моим прогрессом в Twitter, Medium, Dev.to, Hashnode или мой блог WordPress

Первоначально опубликовано на https://www.realpythonproject.com 30 марта 2021 г.