Openstack DevOps and IBM/Informix Certified DBA... · 26 авг 2022
«Переменная» в Python — это не традиционная переменная. Вместо этого это привязка к объекту. По сути, указатель, но на объект, а не на ячейку памяти. Со списком это легко увидеть.
Вот что происходит под капотом, более или менее:
Вы создаете объект списка со значением [1, 2, 3, 4]. Мы назовем этот идентификатор объекта 1. Затем вы привяжете имя «list_one» к идентификатору объекта 1. Вы говорите ему привязать «list_two» к тому же объекту, к которому привязан «list_one». На данный момент они оба привязаны к идентификатору объекта 1. Вы изменяете объект с идентификатором 1. Поскольку список является изменяемым (mutable), содержимое может измениться, и оба имени могут оставаться привязанными к идентификатору 1. Поскольку и «list_one», и «list_two» связаны с идентификатором объекта 1 , печать любого из них возвращает [1, 2, 3, 4, 5].
Что делать с такими вещами, как целые числа и строки? Почему они не ведут себя так же?
Происходит то же самое, но тип объекта имеет значение:
Вы создаете целочисленный объект со значением 1. Мы назовем этот объект с идентификатором 1. Затем вы привяжете имя «int_one» к объекту с идентификатором 1. Вы говорите ему привязать «int_two» к тому же объекту, на который указывает «int_one».
Они оба связаны с идентификатором объекта 1. Вы пытаетесь изменить идентификатор объекта 1, но он неизменяем (immutable), поэтому вы не можете изменить содержимое. Из-за этого он просматривает значение объекта с идентификатором 1, добавляет к нему 10, чтобы получить 11, и создает новый целочисленный объект (идентификатор 2) со значением 11. Затем он повторно привязывает «int_two» к объекту с идентификатором 2, но оставляет «int_one» в покое. Поскольку «int_one» и «int_two» теперь привязаны к разным объектам, их печать даст разные результаты.Если вы снова измените значение «int_two», будет создан третий объект с новым значением, а второй объект останется в памяти без привязок. Не беспокойтесь о потраченной впустую памяти - нужна сборка мусора.
===========================================
В Python аргументы передаются путем присваивания.(official guide)
Фактические параметры (аргументы) вызова функции вводятся в локальную таблицу символов вызываемой функции при ее вызове; таким образом, аргументы передаются с использованием вызова по значению, «где значение всегда является ссылкой на объект, а не значением объекта», там же сноска добавляет:
На самом деле, «вызов по ссылке на объект» был бы лучшим описанием, поскольку, если передается изменяемый (mutable) объект, вызывающая сторона увидит любые изменения, внесенные в нее вызываемой стороной (элементы, вставленные в список).
Вопрос риторический? Разумеется, это передача ссылок по значению. Официальный туториал* называет это "передачей по значению (где значение - это всегда ссылка на объект)". И это ничем не отличается от того, как работают... Читать далее