Различия между передачей по ссылке в C++ и Python

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

Ситуация такова: Насколько я понимаю, Python передает только по ссылке (т.е. передает значение имени переменной, которое, как я полагаю, является адресом местоположения). Под этим впечатлением я вернулся к своему старому учебнику C++, надеясь освежить свою память. о том, как работает передача по ссылке. Но потом я обнаружил, что передача по ссылке в C++ работает иначе, чем передача по ссылке в Python. Например, переназначение переменной влияет на исходную переменную в C++, но не в Python.

Ниже приведены коды и результаты моих экспериментов на C++ и Python. Код C++ взят из книги Программирование на C++: от анализа проблем к разработке программ (6-е издание) Д. С. Малика; код Python был моим переводом кода C++. Обратите внимание, что пример C++ содержит как передачу по значению, так и передачу по ссылке.

Итак, вот мои вопросы: является ли определение передачи по ссылке специфичным для языка? Как работает передача параметров Python? Есть ли какая-то неверная логика в том, что я только что сказал? Любое ясное и простое объяснение непрофессионала будет высоко оценено.

Код C++

//Example 6-13: Reference and value parameters

#include <iostream>

using namespace std;

void funOne(int a, int& b, char v);
void funTwo(int& x, int y, char& w);

int main()
{
    int num1, num2;
    char ch;
    num1 = 10; //Line 1
    num2 = 15; //Line 2
    ch = 'A'; //Line 3
    cout << "Line 4: Inside main: num1 = " << num1
        << ", num2 = " << num2 << ", and ch = "
        << ch << endl; //Line 4
    funOne(num1, num2, ch); //Line 5
    cout << "Line 6: After funOne: num1 = " << num1
        << ", num2 = " << num2 << ", and ch = "
        << ch << endl; //Line 6
    funTwo(num2, 25, ch); //Line 7
    cout << "Line 8: After funTwo: num1 = " << num1
        << ", num2 = " << num2 << ", and ch = "
        << ch << endl; //Line 8
    return 0;
}

void funOne(int a, int& b, char v)
{
    int one;
    one = a; //Line 9
    a++; //Line 10
    b = b * 2; //Line 11
    v = 'B'; //Line 12
    cout << "Line 13: Inside funOne: a = " << a
        << ", b = " << b << ", v = " << v
        << ", and one = " << one << endl; //Line 13
}

void funTwo(int& x, int y, char& w)
{
    x++; //Line 14
    y = y * 2; //Line 15
    w = 'G'; //Line 16
    cout << "Line 17: Inside funTwo: x = " << x
        << ", y = " << y << ", and w = " << w
        << endl; //Line 17
}

Вывод C++

Внутри main: num1 = 10, num2 = 15 и ch = A
Внутри funOne: a = 11, b = 30, v = B и one = 10
После funOne: num1 = 10, num2 = 30 , и ch = A
Внутри funTwo: x = 31, y = 50 и w = G
После funTwo: num1 = 10, num2 = 31 и ch = G

Код Python

def funOne (a, b, v):
    one = a
    a += 1
    b = b * 2
    v = 'B'
    print("Inside funOne: a", a, "b", b, "v", v, "one", one)

def funTwo (x, y, w):
    x += 1
    y = y * 2
    w = 'G'
    print("Inside funTwo: x", x, "y", y, "w", w)

num1 = 10
num2 = 15
ch = 'A'

print("Inside main: num1", num1, "num2", num2, "ch", ch)
funOne(num1, num2, ch)
print("After funOne: num1", num1, "num2", num2, "ch", ch)
funTwo(num2, 25, ch)
print("After funTwo: num1", num1, "num2", num2, "ch", ch)

Вывод Python

Внутри main: num1 10 num2 15 ch A
Внутри funOne: a 11 b 30 v B one 10
После funOne: num1 10 num2 15 ch A
Внутри funTwo: x 16 y 50 w G
После funTwo: num1 10 num2 15 ch A

Спасибо.


person Katharina Huang    schedule 20.01.2017    source источник
comment
Насколько я понимаю, Python передает только по ссылке Нет, подумайте о передаче по значению, но большинство вещей, которые вы передаете, похожи на указатели.   -  person juanchopanza    schedule 21.01.2017
comment
Взгляните на по этой ссылке.   -  person merlin2011    schedule 21.01.2017
comment
Существует большая разница между C++ и Python — ссылки в C++ привязываются к объекту один раз и остаются привязанными навсегда, в то время как ссылки в Python можно свободно переназначать другим объектам. Переменные в Python работают так же, как интеллектуальные указатели в C++.   -  person Mark Ransom    schedule 21.01.2017


Ответы (3)


Ближе всего к ссылке на Python в C++ является интеллектуальный указатель. На самом деле CPython использует указатели с подсчетом ссылок, подобные std::shared_ptr.

Эта функция Python:

def foo(an_int, a_string, list_of_int):

Примерно эквивалентно:

variant foo(shared_ptr<const int> an_int, shared_ptr<const string> a_string, shared_ptr<vector<shared_ptr<const int>>> list_of_int) {
person Mark Ransom    schedule 21.01.2017

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

В C++ это необходимо указать явно в функции, поставив & перед именем параметра в объявлении функции. В противном случае параметры передаются по значению (хотя в случае с массивами имя массива распадается на указатель на его первый элемент, так что это похоже на передачу по ссылке).

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

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

person Barmar    schedule 20.01.2017
comment
Передача по значению означает создание копии объекта в C++. Использование того же самого термина для обозначения Python приводит к недопониманию. Даже передача чего-то простого, например float, не создает копию объекта. - person Mark Ransom; 21.01.2017
comment
@MarkRansom Но, поскольку нет возможности изменить поплавок на месте, вы не можете отличить копию от некопии. Проблема с такими вопросами в целом заключается в том, что объяснение связано с деталями того, как работают переменные в каждом языке. - person Barmar; 21.01.2017

Аргументы Python передаются по присваиванию. Здесь есть хорошее объяснение -

Как передать переменную по ссылке?

person Illusionist    schedule 20.01.2017