Пропустить до содержимого

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

[

Python: Передача по ссылке - Определение”Pass by Reference”

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

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

Поскольку вы даете функции ссылку на существующую переменную, все операции, выполняемые с этой ссылкой, напрямую влияют на переменную, на которую она ссылается. Давайте рассмотрим некоторые примеры, чтобы увидеть, как это работает на практике.

Ниже вы увидите, как передать переменные по ссылке в C#. Обратите внимание на использование ключевого слова ref в выделенных строках:

using System;
class Program
{
static void Main(string[] args)
{
int arg;
// Passing by reference.
// Значение "arg".
MultiplyByTwo(ref arg);
Console.WriteLine(arg); // Output: 100
// Nullable types with "ref" keyword.
int? nullableArg = null;
Console.WriteLine(nullableArg.HasValue); // Output: False
UpdateNullable(ref nullableArg);
Console.WriteLine(nullableArg.HasValue); // Output: True
Console.Read();
}
static void MultiplyByTwo(ref int number)
{
number *= 2;
}
static void UpdateNullable(ref int? nullableNumber)
{
nullableNumber = 10;
}
}

В этом примере создается метод MultiplyByTwo, который принимает аргумент number по ссылке с помощью ключевого слова ref. Затем аргумент number внутри метода умножается на 2, что приводит к изменению значения переменной arg внутри метода Main.

Еще одним интересным примером является использование ref с типами, допускающими значения null. Это показано в методе UpdateNullable, который устанавливает значение nullableNumber равным 10. После вызова этого метода значение nullableArg в методе Main также изменяется.

Но как эти понятия относятся к Python? Давайте рассмотрим, как Python обрабатывает передачу аргументов в функции.

Передача аргументов в Python

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

Например, рассмотрим следующий код:

def double(x):
x *= 2
num = 10
double(num)
print(num) # Output: 10

В этом примере определена функция double, которая принимает аргумент x. Внутри функции значение x умножается на 2. Однако, когда мы вызываем функцию double и передаем в нее переменную num, исходное значение num (равное 10) остается неизменным.

В данном случае функция работает с копией значения num, а не с самой переменной num. Таким образом, функция не модифицирует исходную переменную.

Эта особенность языка Python немного отличается от того, как работают некоторые другие языки программирования, такие как C# или C++. Но существуют способы эмулировать передачу по ссылке в Python и достичь подобного поведения функций.

Воспроизведение передачи по ссылке с помощью Python

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

  • Лучшая практика: возвращение и переустановка значения внутри функции.
  • Лучшая практика: использование атрибутов объекта.
  • Лучшая практика: использование словарей и списков.

Давайте рассмотрим каждый из этих подходов более подробно.

Лучшая практика: возвращение и переустановка значения

Первый способ эмулировать передачу по ссылке в Python - это возврат значения из функции и его переустановка в соответствующей переменной. Рассмотрим следующий пример:

def double(x):
return x * 2
num = 10
num = double(num)
print(num) # Output: 20

В этом примере мы определяем функцию double, которая принимает аргумент x и возвращает его значение, умноженное на 2. Затем мы вызываем функцию double и присваиваем возвращаемое значение переменной num. В результате значение num становится равным 20.

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

Лучшая практика: использование атрибутов объекта

Второй способ эмулировать передачу по ссылке в Python - это использование атрибутов объекта. Объекты в Python являются изменяемыми, что означает, что их значения могут быть изменены непосредственно. Рассмотрим следующий пример:

class Number:
def __init__(self, num):
self.num = num
def double(number):
number.num *= 2
num = Number(10)
double(num)
print(num.num) # Output: 20

В этом примере мы определяем класс Number, который имеет один атрибут num. Затем мы определяем функцию double, которая принимает аргумент number и умножает его атрибут num на 2. Затем мы создаем экземпляр класса Number и вызываем функцию double с этим экземпляром в качестве аргумента. Результатом будет изменение значения атрибута num экземпляра класса Number.

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

Лучшая практика: использование словарей и списков

Третий способ эмулировать передачу по ссылке в Python - это использование словарей и списков. Словари и списки являются изменяемыми структурами данных в Python, что позволяет нам изменять их содержимое. Рассмотрим следующий пример:

def double(values):
for i in range(len(values)):
values[i] *= 2
nums = [1, 2, 3, 4]
double(nums)
print(nums) # Output: [2, 4, 6, 8]

В этом примере мы определяем функцию double, которая принимает аргумент values - список чисел. Затем мы проходим по списку с помощью цикла for и умножаем каждый элемент на 2. После вызова функции double значения в списке nums обновляются.

Этот подход позволяет нам изменять значения внутри списка, а не копировать список и работать с копией значений.

Вывод

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

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