A question on modification of a list via a function invocation

Steve D'Aprano steve+python at pearwood.info
Mon Sep 4 09:46:19 EDT 2017


On Mon, 4 Sep 2017 01:31 pm, Stefan Ram wrote:

> Steve D'Aprano <steve+python at pearwood.info> writes:
>>That makes arrays (and strings) in C a bit of an odd corner case, and an
>>exception to the usual rules, like unboxed machine types in Java. We should
>>acknowledge them, but as exceptional cases, and we should note that Python has
>>no similar exceptional cases. All values in Python are first-class, and all
>>are passed in precisely the same way.
> 
>   I look at the following "generic" (C, Java, Python, ...)
>   pseudocode program:
> 
> define f( x ):
>   x = 9;
>   return;
> 
>   ...
> 
> a = 2;
> f( a );
> print( a );
> 
>   My definition: When the assignment »x = 9« has an effect on »a«,
>   then it's »call by reference«. Otherwise, it's call by value.

Sorry Stefan, that is the same trap that many others fall into. You are assuming
that there are exactly two evaluation conventions:

- pass by reference
- pass by value

and so if a language doesn't do one, it must do the other.

This is a false dichotomy! There are many more than just two conventions:

- pass by value
- pass by reference
- pass by name
- pass by object reference (object sharing)
- pass by need
- pass by future
- pass by copy-restore

and more.

https://en.wikipedia.org/wiki/Evaluation_strategy


You are right that Python is not pass by reference. You cannot write a general
swap procedure in Python:

a = 1
b = 2
swap(a, b)
assert a == 2 and b == 1


like you can in Pascal:

procedure swap(var a:integer, var b: integer);
  var
    tmp: integer;
  begin
    tmp := a;
    a := b;
    b := tmp;
  end;


But that's not enough to prove that Python is pass by value. One way to
demonstrate that Python is pass by value is to show that passing an argument to
a function makes a copy of it:

def is_copy_made(argument, idnumber):
    """Decide whether the argument was copied or not."""
    if id(argument) == idnumber:
        print('IDs match, no copy was made')
    else:
        print('IDs are different, copy was made')

value = {}  # any object

is_copy_made(value, id(value))



Python will ALWAYS print "IDs match" (provided you pass the actual id of the
argument -- no cheating by passing some other id, or an arbitrary number).
Python doesn't copy values when you pass them to functions.

Hence Python is neither pass by reference nor pass by value.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list