0

I have a little bit of C++ background. I am currently learning Python and am trying to understand how the function parameters are passed. I know this question is asked numerous times up here, but since I am not a Computer Science major, a lot of discussions threads are rather esoteric to me, plus, I've not seen a lot of comparisons on this topic between different languages, so I thought I'd give a new post a try.

The situation is this: My understanding is that Python only pass by reference (i.e. pass the value of the variable name, which I believe is the location address.) Under this impression, I went back to my old C++ textbook hoping to refresh my memory on how pass by reference works. But then I discovered that passing by reference in C++ seemed to work differently from passing by reference in Python. An example would be that variable reassignment affected the original variable in C++ but not in Python.

Below are codes and outputs of my experiments in C++ and in Python. The C++ code was from C++ Programming: From Problem Analysis to Program Design (6th Edition) by D.S. Malik; the Python code was my translation of the C++ code. Note that the C++ example contains both pass-by-value and pass-by-reference.

So, here come my questions: Is the definition of pass-by-reference language-specific? How does Python parameter passing work? Are there any incorrect logics in what I just said? Any clear and simple layman explanation would be greatly appreciated.

C++ code

//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++ output

Inside main: num1 = 10, num2 = 15, and ch = A
Inside funOne: a = 11, b = 30, v = B, and one = 10
After funOne: num1 = 10, num2 = 30, and ch = A
Inside funTwo: x = 31, y = 50, and w = G
After funTwo: num1 = 10, num2 = 31, and ch = G

Python code

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 output

Inside main: num1 10 num2 15 ch A
Inside funOne: a 11 b 30 v B one 10
After funOne: num1 10 num2 15 ch A
Inside funTwo: x 16 y 50 w G
After funTwo: num1 10 num2 15 ch A

Thanks.

  • "My understanding is that Python only pass by reference" No, think passing by value, but most things you pass are like pointers. – juanchopanza Jan 20 '17 at 22:51
  • Take a look at [this link](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference). – merlin2011 Jan 20 '17 at 22:54
  • 2
    There's a big difference between C++ and Python - references in C++ are bound once to an object and stay bound forevermore, while references in Python are free to be reassigned to different objects. Variables in Python work much like smart pointers in C++. – Mark Ransom Jan 20 '17 at 23:04
  • @juanchopanza: More precisely, *all* things you pass are like pointers. There's no concept of a primitive in Python, even passing an `int` is actually passing a pointer to an object that knows it is an `int` and contains the `int`s value. There's no way to pass anything that's not a pointer at the Python level (even `ctypes` functions pass pointers, Python just unwraps for you for the C call). The only difference between passed arguments is that some are effectively pointers to `const` objects, while others are pointers to mutable objects (based on the object's type; you can't choose). – ShadowRanger Jan 25 '23 at 15:51

3 Answers3

3

The closest thing to a Python reference in C++ is a smart pointer. In fact CPython uses reference counted pointers similar to std::shared_ptr.

This Python function:

def foo(an_int, a_string, list_of_int):

Is roughly equivalent to:

variant foo(shared_ptr<const int> an_int, shared_ptr<const string> a_string, shared_ptr<vector<shared_ptr<const int>>> list_of_int) {
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

"Pass by reference" means that the function receives the address of the caller's variable, and when it assigns to the parameter it modifies the caller's variable.

In C++, this has to be specified explicitly in the function, by putting & before the parameter name in the function declaration. Otherwise, parameters are passed by value (although in the case of arrays, the array name decays to a pointer to its first element, so it's similar to pass by reference).

Python does not do this at all, it uses pass by value. But if the value is a structured object like a list or dictionary, the value is a reference to the object, not a copy of it. So if the function modifies the contents of the object, it affects the caller's variable as well. But it's not the same as pass by reference, because if the function simply assigns to the parameter variable it has no effect on the caller's variable.

And this does not happen at all for immutable values such as numbers and strings. There's no way to modify the contents of such values. All you can do is assign to the variable, and as stated above that has no effect on the caller's variable.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    "Pass by value" means making a *copy* of an object in C++. Using that same term to refer to Python leads to misunderstanding. Even passing something simple like a `float` doesn't make a copy of the object. – Mark Ransom Jan 20 '17 at 23:07
  • @MarkRansom But since there's no way to modify the float in place, you can't tell the difference between a copy and non-copy. The problem with questions like this in general is that the explanation is tied into the details of how variables work in each language. – Barmar Jan 20 '17 at 23:13
0

Python arguments are passed by assignment. There is good explanation here-

How do I pass a variable by reference?

Community
  • 1
  • 1
Illusionist
  • 5,204
  • 11
  • 46
  • 76