pythonvariablesreferencepass-by-reference

Python functions call by reference


In some languages you can pass a parameter by reference or value by using a special reserved word like ref or val. When you pass a parameter to a Python function it never alters the value of the parameter on leaving the function.The only way to do this is by using the global reserved word (or as i understand it currently).

Example 1:

k = 2

def foo (n):
     n = n * n     #clarity regarding comment below
     square = n
     return square

j = foo(k)
print j
print k

would show

>>4
>>2

showing k to be unchanged.

In this example the variable n is never changed

Example 2:

n = 0
def foo():
    global n
    n = n * n
    return n

In this example the variable n is changed.

Is there any way in Python to call a function and tell Python that the parameter is either a value or reference parameter instead of using global?


Solution

  • You can not change an immutable object, like str or tuple, inside a function in Python, but you can do things like:

    def foo(y):
      y[0] = y[0]**2
    
    x = [5]
    foo(x)
    print x[0]  # prints 25
    

    That is a weird way to go about it, however, unless you need to always square certain elements in an array.

    Note that in Python, you can also return more than one value, making some of the use cases for pass by reference less important:

    def foo(x, y):
       return x**2, y**2
    
    a = 2
    b = 3
    a, b = foo(a, b)  # a == 4; b == 9
    

    When you return values like that, they are being returned as a Tuple which is in turn unpacked.

    edit: Another way to think about this is that, while you can't explicitly pass variables by reference in Python, you can modify the properties of objects that were passed in. In my example (and others) you can modify members of the list that was passed in. You would not, however, be able to reassign the passed in variable entirely. For instance, see the following two pieces of code look like they might do something similar, but end up with different results:

    def clear_a(x):
      x = []
    
    def clear_b(x):
      while x: x.pop()
    
    z = [1,2,3]
    clear_a(z) # z will not be changed
    clear_b(z) # z will be emptied