У меня есть немного C ++ фона. В настоящее время я изучаю Python и пытаюсь понять, как передаются параметры функции. Я знаю, что этот вопрос неоднократно задавался здесь, но, поскольку я не специалист в области компьютерных наук, многие темы для обсуждения довольно эзотеричны для меня, к тому же я не видел много сравнений по этой теме между разными языками, так что я решил попробовать новый пост.
Ситуация такова: я понимаю, что Python передает только по ссылке (т.е. передает значение имени переменной, которое, как я считаю, является адресом местоположения). Под этим впечатлением я вернулся к своему старому учебнику по C ++ в надежде обновить свою память о том, как работает передача по ссылке. Но затем я обнаружил, что передача по ссылке в C ++, похоже, работает иначе, чем передача по ссылке в Python. Примером может служить то, что переназначение переменных влияет на исходную переменную в C ++, но не в Python.
Ниже приведены коды и результаты моих экспериментов на C ++ и Python. Код C ++ был из Программирование на C ++: от анализа проблем до разработки программ (6-е издание) Д.С. Малик; код Python был моим переводом кода C ++. Обратите внимание, что пример C ++ содержит как передачу по значению, так и передачу по ссылке.
Итак, вот мои вопросы: Является ли определение языка передачи по ссылке конкретным? Как работает передача параметров Python? Есть ли неправильные логики в том, что я только что сказал? Любое ясное и простое объяснение непрофессионала будет с благодарностью.
//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
}
Внутри 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
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)
Внутри основной: № 1 10 № 2 15 ч А
Внутри funOne: a 11 b 30 v B один 10
После веселья: число1 10 число2 15 ч А
Внутри веселья два: x 16 y 50 w G
После веселья два: число1 10 число2 15 ч А
Благодарю.
Самая близкая вещь к ссылке на 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) {
Аргументы Python передаются по присваиванию. Здесь есть хорошее объяснение
«Передача по ссылке» означает, что функция получает адрес переменной вызывающего, а когда она присваивается параметру, она изменяет переменную вызывающего.
В C ++ это должно быть явно указано в функции, помещая &
перед именем параметра в объявлении функции. В противном случае параметры передаются по значению (хотя в случае массивов имя массива затухает до указателя на его первый элемент, поэтому оно аналогично передаче по ссылке).
Python вообще не делает этого, он использует проход по значению. Но если значение представляет собой структурированный объект, такой как список или словарь, значение является ссылкой на объект, а не его копией. Таким образом, если функция изменяет содержимое объекта, она также влияет на переменную вызывающего. Но это не то же самое, что передача по ссылке, потому что если функция просто присваивает значение переменной параметра, это не влияет на переменную вызывающего.
И это не происходит вообще для неизменных значений, таких как числа и строки. Нет способа изменить содержимое таких значений. Все, что вы можете сделать, это присвоить переменную, и, как указано выше, это не влияет на переменную вызывающего.