Python аргумент по ссылке

Изменяемые и неизменяемый типы объектов#

Программисту C/C++ может показаться, что во второй строке увеличивается на 1 значение, хранящееся в созданном на первой строке целочисленном объекте. На самом деле это не так: создаётся новый объект, хранящий результат вычисления выражения a + 1 , а затем имя a связывается с этим новым объектом. Чтобы продемонстрировать это, напечатаем идентификатор объекта до и после увеличения на 1.

a = 0 print(a, id(a)) a += 1 print(a, id(a)) 
0 2835673868560 1 2835673868592

Видим, что идентификатор меняет свое значение, а значит имя a ссылается на разные объекты до и после инструкции a += 1 .

В python все типы объектов можно разделить на два вида: изменяемые ( mutable ) и неизменяемые ( immutable ).

  • Значение, хранящееся в объекте неизменяемого типа, невозможно изменить никакими способами. Единственный способ получить объект такого типа с другим значением — создать новый объект с нужным значением.
  • Значение, хранящееся в объекте изменяемого типа, можно изменить не создавая новый объект. Изменения объекта возможно за счет вызова его методов или применения к нему операторов.

Все встроенные числовые типы ( bool , int , float , complex , ( decimal , fractions , которые также присутствуют в стандартной библиотеке, но обсуждаться здесь не будут)) являются неизменяемыми. Единственный изменяемый тип объектов, с которым мы уже сталкивались — list . Продемонстрируем его изменяемость.

Читайте также:  Перевод системы исчисления python

Оператор “ += ” определен и для списков, только с другим эффектом: он расширяет список слева от него, элементами итерируемого объекта справа.

l = [42] print(l, id(l)) l += "abc" print(l, id(l)) 
[42] 1384847112704 [42, 'a', 'b', 'c'] 1384847112704

Для неизменяемого объекта a выражение a += b эквивалентно выражению a = a + b .

Разделяемый ссылки#

Изменяемость и неизменяемость играет наибольшую роль в случае, когда несколько имен ссылаются на один и тот же объект.

Разделяемые ссылки на неизменяемый объект#

Создадим две ссылки a и b на один и тот же объект целочисленного типа.

Во второй строке создаётся имя b и оно связывается с объектом, на которое указывает имя a . Убедиться, что имена указывают на один и тот же объект, можно сравнив их адреса ( id(a) == id(b) ). В python помимо оператора сравнения на равенство “ == ”, ещё есть оператор сравнения на идентичность is , который по сути дела сравнивает ссылки на объекты.

Сравнение на идентичность — более сильная концепция, чем сравнение на равенство: если объекты по ссылками идентичны (один и тот же объект, никак иначе), то они гарантировано равны, но не наоборот, равные объекты могут являться разными сущностями.

Источник

Что вы не знали и передаче параметров в функции

В Python при вызове функции используется передача параметров по ссылке или по значению? Сегодня мы попытаемся разобраться. В этой статье вы узнаете: Python не использует модели передачи по ссылке и по значению, а применяет передачу параметров через присваивание; о характеристиках объектов; разницу между изменяемыми(mutable) и неизменяемыми (immutable) объектами.

Передача параметров в других языках

Многие языки программирования предлагают две модели передачи параметров в функции/процедуры:

И то, какую модель использует язык программирования, важно знать, поскольку за эффективность кода отвечает программист лично. А теперь попробуем разобраться, какую модель использует язык Python.

Использует ли Python модель передачи по значению?

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

В Python не применяется модель передачи по значению, но в некоторых случаях можно видеть нечто похожее. Например, рассмотрим следующий пример:

def foo(x): x = 4 a = 3 foo(a) print(a) # 3

Функция вызывается, но изменения оказанные на переменную a больше не действую после возврата из функции, ведь a всё ещё равна 3. Поэтому может показаться, что используется передача по значению, но это не так. Python не копирует значения параметров при вызове функции. Если мы рассмотрим другую функцию:

def clearly_not_pass_by_value(my_list): my_list[0] = 42 l = [1, 2, 3] clearly_not_pass_by_value(l) print(l) # [42, 2, 3]

— то мы четко видим, что элемент исходного списка l был изменен после вызова функции. Значит ли это, что объект списка использовался один и тот же?

Использует ли Python передачу по ссылке?

При передачи по ссылке в момент вызова функции передаются адреса переменных, причем с адресами работают так, как если бы это была обычная переменная (поэтому не нужно дополнительно проводить разыменование, как это делается в Си). Такая модель подразумевает, что исходные переменные и параметры функции — это одни и те же объекты. Изменяя параметры в теле функции, вы изменяете их и в вызывающем контексте.

Так вот Python не использует и эту модель передачи параметров. Взглянем на следующий код:

def not_pass_by_reference(my_list): my_list = [42, 73, 0] l = [1, 2, 3] not_pass_by_reference(l) print(l) # [1, 2, 3]

Мы предполагаем, что функция должна полностью изменить список, но этого не происходит, он остался прежним. Так какая же модель передачи параметров в функции в используется в Python?

Объекты в Python

В Python всё является объектом. Каждый объект характеризуется следующими характеристиками:

  • идентифицирумостью (каждый объект обладает уникальными номером),
  • типом (каждый тип обладает своими операциями, которые можно применять),
  • содержимое самого объекта.

Эти характеристики можно узнать следующим образом:

>>> id(obj) 2698212637504 >>> type(obj) >>> obj [1, 2, 3]

Эти знания нам пригодятся в дальнейшем.

Изменяемые и неизменяемые объекты

Объекты в Python могут быть изменяемыми (mutable) или неизменяемыми (immutable). Это свойство полностью зависит от типа объекта. Иными словами, не/изменяемость является характеристикой типа, а не конкретных объектов.

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

Список (list) является изменяемым типом данных. Почему? Потому что списки являются контейнерами: в них можно добавлять данные и из можно удалять данные. Иными словами, их можно спокойно изменять.

Ниже приведен пример того, как содержимое списка меняется, но идентификатор остается тем же самым, что бы мы ни делали.

>>> obj = [] >>> id(obj) 2287844221184 >>> obj.append(0); obj.extend([1, 2, 3]); obj [42, 0, 1, 2, 3] >>> id(obj) 2287844221184 >>> obj.pop(0); obj.pop(0); obj.pop(); obj 42 0 3 [1, 2] >>> id(obj) 2287844221184

С другой стороны, содержимое неизменяемых объектов нельзя изменить. Они существует так, как их инициализировали в первый раз. Строка str является хорошим примером неизменяемого типа.

Вызывая различные методы, призванные как-то модифицировать состояние, объекты с неизменяемым типом что-то возвращают, в отличие от изменяемых. Например, метод списка append ничего не возвращает (он изменяет существующий), а методы строки возвращают новую строку (новый объект):

>>> [].append(0) # Ничего не возвращается >>> "Hello, world!".upper() # Возвращается новая строка 'HELLO, WORLD!"

Другим сигналом неизменяемости объекта является невозможность изменить отдельные его элементы, например, при присваивании через индексы:

>>> obj[0] 'H' >>> obj[0] = "h" Traceback (most recent call last): File "", line 1, in TypeError: 'str' object does not support item assignment

Для справки, в Python встроенные типы:

Переменные и их имя

Ещё необходимо понять, что название переменной — это не то же самое, что и сам объект. Например, имя obj был просто некой меткой, которая была связана с объектом с идентификатором 2287844221184 , типом list и содержимым 1, 2, 3 . Это называется механизмом связывания, о котором мы говорил тут.

Мы вольны связывать и другие метки к этому же самому объекту:

>>> foo = bar = baz = obj >>> id(foo) 2698212637504 >>> id(bar) 2698212637504 >>> id(baz) 2698212637504 >>> id(obj) 2698212637504 # При этом, если изменить объект: >>> obj = 5 >>> id(obj) 94830320197056

Как видим все метки обращаются к одному объекту. В Python даже есть специальный оператор is , который проверяет являются ли два объекты одной сущностью (читай: равны ли их id ).

>>> foo is obj True >>> bar is foo True >>> obj is foo True

Изменяя содержимое через одну переменную, эти изменения можно пронаблюдать через другие, поскольку это один и тот же объект. При этом нужно понимать, объекты, которые имеют тот же тип и содержимое, но не id , не являются одним объектом:

В Python используется передача параметров через присваивание

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

Так, если мы передаем неизменяемые параметр (например, int ), то у нас нет возможности хоть как-то его изменить. Каждый раз, когда используется присваивание, то создается новый объект, хоть и имеющий то же самое имя. Взгляните на данный пример:

def foo(bar): bar = 3 return bar a = 5 foo(a)

Вызов функции для неизменяемого типа подразумевает, что используется связывание bar = 5 . Сразу после этого в теле функции осуществляется второе связывание bar = 3 . Но все эти объекты разные. Поэтому при использовании неизменяемых объектов в качестве параметров, их передача осуществляется как будто по схеме передаче значений.

Источник

Передача по ссылке в Python

Передача по ссылке в Python

  1. Определение передачи по ссылке в функции Python
  2. Пример передачи по ссылке в Python
  3. Объяснение

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

Определение передачи по ссылке в функции Python

Есть много способов определить аргумент в функции в Python; один из этих процессов — передача по ссылке. Слово передать здесь означает передать или передать аргумент функции. Тогда по ссылке означает, что аргумент, переданный функции, в основном упоминается как существующая переменная, а не как отдельная копия этой переменной. В этом методе определения аргумента в функции на переменную, на которую была сделана ссылка, в основном влияет любая выполняемая операция.

Пример передачи по ссылке в Python

def fun(x):  x.append('Sam')  print("While calling the function:",x)  x=['Hello'] print("Before calling the function:",x) fun(x) print("After calling the function:",x) 
Before calling the function: ['Hello'] While calling the function: ['Hello', 'Sam'] After calling the function: ['Hello', 'Sam'] 

Объяснение

В приведенном выше примере функция сначала определяется переменной x . Здесь метод append используется с x для добавления к имени элемента sam . После этого составляется список с использованием элемента x , в котором только один элемент, то есть hello . После печати списка функция, которая была определена изначально, вызывается вместе со своим аргументом x . После вызова функции обратите внимание, что добавленный элемент в самой функции был добавлен в список x .

Этот процесс показывает, как работает передача по ссылке . Функция всегда влияет на изменяемые объекты (объекты, которые могут изменять свое значение или состояние), хранящиеся в переменной, используемой в качестве аргумента функции.

Lakshay Kapoor is a final year B.Tech Computer Science student at Amity University Noida. He is familiar with programming languages and their real-world applications (Python/R/C++). Deeply interested in the area of Data Sciences and Machine Learning.

Сопутствующая статья — Python Function

Источник

Оцените статью