

Is Python call-by-value or call-by-reference? Neither. - jknupp
http://www.jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

======
Jach
Wrong. It's call-by-value, the confusion comes from what, in Python, is
considered a value (and when a value is mutable, which is always (with a
little ctypes magic), even the built-in number 4). And just like in Java,
which also is always call-by-value, Python passes pointers-by-value under the
hood which allows for some easy modification.

There is an easy test to see if a language supports call-by-reference or not:

    
    
        a = 3
        b = 4
        swap(a,b)
        print a, b # 4 3
    

C++ can do this, C can't, C# can't (if you think it can, then so can C),
Python can't, Java can't. Therefore, all of those but C++ are call-by-value in
all cases.

Edit: I hasten to add, the swap() function should be implemented
"traditionally". i.e.:

    
    
        def swap(x, y):
          temp = x
          x = y
          y = temp

~~~
jknupp
To say that because Python passes pointers-by-value under the hood (which is
true for cpython, but not other implementations) is not useful. "Call by
value" and "Call by reference" have reasonably precise definitions, and Python
fits neither. See
<http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing> for a
discussion of the difference.

~~~
calinet6
Re: call-by-sharing: "Although this term has widespread usage in the Python
community, identical semantics in other languages such as Java and Visual
Basic are often described as call-by-value, where the value is implied to be a
reference to the object."

It's behaviorally call-by-value, where the value is always an object
reference.

The difference is only mildly interesting, and the fervor with which you're
arguing about it is wholly uninteresting, bordering on misleading. This is a
semantic distinction with little to no use, and just serves to further confuse
the rather simple and clear behavior.

~~~
andrewcooke
afaik, this approach is from (or at least strongly championed at)
comp.lang.python, and i would guess that their experience is that it is the
most successful way of explaining python to new users there.

it's not so terrible - it works well enough for c.l.p, and anyone used to call
by value with references/pointers is capable of working things out themselves.

really, it's largely a python (and c.l.p) cultural thing. you're berating some
guy who's just a messenger for something that, in its context, doesn't do any
harm (indeed, might help some newbies) (i don't have any skin in this game,
but the guys on c.l.p do great work helping others; if this helps them it's
fine by me).

~~~
calinet6
You're right, it doesn't do any harm. But I think the way he's presenting it
is harmful, as it's more confusing and not intended as explanation, but more
as pointing out a distinction that isn't really present. He's very fervently
defending a minor point of semantics, and I feel that's harmful.

------
brabbins
Perhaps this is a digression, but there are some misunderstandings in this
blog post about the memory model in his C++ example. Since the author goes to
lengths to be precise and exact in terminology and his explanations, it would
be good to clarify some things.

For the example code C++ given:

    
    
        string some_guy = "Fred";
        // ...
        some_guy = "George";
    

Here is the author's explanation:

    
    
        In the above, the variable some_guy refers to a location in
        memory, and the value 'Fred' is inserted in that location (indeed,
        we can take the address of some_guy to determine the portion of
        memory to which it refers). Later, the contents of the memory
        location referred to by some_guy are changed to 'George'. The
        previous value no longer exists; it was overwritten. This likely
        matches your intuitive understanding (even if you don't program in
        C++).
    

There are several incorrect statements here.

A. "the variable some_guy refers to a location in memory, and the value 'Fred'
is inserted in that location" Not true. The variable some_guy refers to a
location in memory, but that location contains a _pointer_ to a region of
memory with the value "Fred". More on this in a bit.

B. "indeed, we can take the address of some_guy to determine the portion of
memory to which it refers". Again, not true in the way the author probably
intended. The address of 'some_guy' will be the address on the stack where the
variable is located. The value at that address on the stack will be a pointer
to a separate region of memory containing "Fred".

C. "Later, the contents of the memory location referred to by some_guy are
changed to 'George'." To be precise, the contents of the memory location
referred to by some_guy are changed to a new _pointer_ to a different region
of memory containing "George".

D. "the previous value no longer exists; it was overwritten." The values
"Fred" and "George" exist through the entire lifetime of the program. They are
string constants, which are compiled in to the data section of the program
binary. The author is correct on one point: the value of 'some_guy' is
overwritten during the reassignment. However, the value in this case is simply
a pointer, not a string.

We can verify my claims experimentally. On my system (Ubuntu 11.04 32-bit, g++
4.5.2), I wrote the following test program:

    
    
        //a.cpp
        #include <string>
        using namespace std;
        int main()
        {
          string some_guy = "Fred";
          some_guy = "George";
          return 0;
        }
    

Compile like this: $ g++ -O0 a.cpp -o a

Now, we can disassemble the "main" function to see exactly what is going on in
the executable:

    
    
       $ objdump -d a
       a:     file format elf32-i386
       ...
       08048614 <main>:
        8048614:	55                   	push   %ebp
        8048615:	89 e5                	mov    %esp,%ebp
        8048617:	83 e4 f0             	and    $0xfffffff0,%esp
        804861a:	53                   	push   %ebx
        804861b:	83 ec 2c             	sub    $0x2c,%esp
        804861e:	8d 44 24 1f          	lea    0x1f(%esp),%eax
        8048622:	89 04 24             	mov    %eax,(%esp)
        8048625:	e8 06 ff ff ff       	call   8048530 <_ZNSaIcEC1Ev@plt>
        804862a:	8d 44 24 1f          	lea    0x1f(%esp),%eax
        804862e:	89 44 24 08          	mov    %eax,0x8(%esp)
        8048632:	c7 44 24 04 80 87 04 	movl   $0x8048780,0x4(%esp)
        8048639:	08 
        804863a:	8d 44 24 18          	lea    0x18(%esp),%eax
        804863e:	89 04 24             	mov    %eax,(%esp)
        8048641:	e8 ca fe ff ff       	call   8048510 <_ZNSsC1EPKcRKSaIcE@plt>
        8048646:	8d 44 24 1f          	lea    0x1f(%esp),%eax
        804864a:	89 04 24             	mov    %eax,(%esp)
        804864d:	e8 ce fe ff ff       	call   8048520 <_ZNSaIcED1Ev@plt>
        8048652:	c7 44 24 04 85 87 04 	movl   $0x8048785,0x4(%esp)
        ...
    

In this case, we are interested in the following two lines:

    
    
        8048632:	c7 44 24 04 80 87 04 	movl   $0x8048780,0x4(%esp)
    

and

    
    
        8048652:	c7 44 24 04 85 87 04 	movl   $0x8048785,0x4(%esp)
    

0x4(%esp) is the address on the stack of our 'some_guy' variable. We are
moving an "immediate" (constant) value into that location. What does that
immediate refer to? Again, let's find out experimentally:

    
    
        $ objdump -s -j .rodata a
        a:     file format elf32-i386
        Contents of section .rodata:
         8048778 03000000 01000200 46726564 0047656f  ........Fred.Geo
         8048788 72676500 00000000                    rge.....
    

Notice that the address of "Fred" is 0x8048778 + 8 = 0x8048780, which is
exactly the immediate value from the disassembled main function.

This means that our variable "some_guy" really is a pointer, and nothing more.
The strings "Fred" and "George" are statically allocated in the data section
of the binary, meaning they stick around indefinitely.

------
mistercow
A lot of comments here are talking about how it's "really" just call-by-value.
I want to explain why this is unproductive.

First, let's acknowledge that the context we're discussing is explaining to
someone new to Python how Python works with function arguments.

Now, if someone asks if lead-acid batteries work using chemistry, and you say
"they use physics", then they will probably end up with a fairly inaccurate
picture of how lead-acid batteries work. What you've told them is
_technically_ correct, but it isn't practically useful.

It is the same if someone asks how Python passes arguments to functions and
you say "it's pass-by-value". You've told them something technically correct,
but they're going to think inaccurate things like that passing an object to a
function copies all of the object's properties like a struct in C.

Even if you say "it's pass-by-value but the values are not what you think",
you haven't actually _added_ to their understanding by that phrase. You're
better off explaining _conceptually_ how it works, describing it as "call-by-
sharing", and then explaining what that means. It will signal their brain to
allocate space for a new concept, and not to drag in erroneous ideas from
existing concepts. After they understand how it works, you can explain that
call-by-sharing is actually just a spoonful of sugar to help the call-by-value
go down.

Here's the thing: words are there to help us communicate. If you use a word in
a way that is technically correct but _conveys the wrong idea_ to your
listener, you're doing it wrong.

Here's the other thing: this is computer science. In computer science, as in
all math, you often encounter a concept that is "really just" some other
concept. When you come to that realization about a concept that you understand
superficially, it can be transformative, taking you to a deeper level of
comprehension. When someone asks you about the concept, you'll want to share
that deep comprehension with them, so it's natural to want to jump right into
it and explain it by connecting it to the general case. But they _will not_
understand if you do that.

You can't teach someone addition by starting with ring theory, after all.

~~~
void-star
On the contrary, I think inventing a new class of of "call-by-X" function
arguments makes it harder to explain Python to newcomers. I would clarify that
I think I'm talking about seasoned programmers, and you probably mean somebody
who's a fairly new to programming in general. It's a tough balance to strike,
but I still think common semantics are best.

The concepts of call-by-value vs call-by-reference are simple and easy to
distinguish once somebody has understood this basic concept in languages. I
don't mean to disregard newcomers, though. And in-fact I think that it is
doing a disservice to them to make python sound like it is radically different
and more complicated than other languages. Instead I think a newcomer is best
served by helping them grasp basic, common language concepts as they apply to
python as well as other languages.

I really also need call out that there seem to be a lot of inaccuracies with
regards to other languages than python on this thread and even some confusing
terminology and analogies by the article's author. Specifically there seem to
be a lot of misunderstandings about C (and even C++) flying around and being
perpetuated here.

For example, you compared passing a python object to passing a struct in C.
Passing a C struct to a function does _not_ copy all the fields of the struct.
It passes a reference (pointer) to the function, which the function then uses
to access the fields (or properties if you will) in the struct directly at
their original location in memory.

You do get automatic copies of primitive numeric types when you pass them to
functions in C. The reasoning and distinction is pretty simple: they fit in
hardware registers.

But, a struct, an array, or a string (or character array) is always going to
be passed as a pointer. When you pass it to a function, the only way you get a
copy of it is if you explicitly copy the value to a new location in memory and
point to it. You can of-course also pass a pointer to a numeric value to a
function as well (as in func(int *var)) instead of the actual value (as in
func(int var)), in which case the same semantics apply.

~~~
mistercow
>On the contrary, I think inventing a new class of of "call-by-X" function
arguments makes it harder to explain Python to newcomers.

Then I think you may have forgotten what it's like to move to a call-by-
sharing language for the first time.

>Passing a C struct to a function does _not_ copy all the fields of the
struct. It passes a reference (pointer) to the function, which the function
then uses to access the fields (or properties if you will) in the struct
directly at their original location in memory.

I'm sorry, but everything you said there is wrong. Try it out for yourself:
<https://gist.github.com/4073329>

~~~
void-star
Wow ok.. I'm going to try to be polite. I don't think _you_ tried it as you
suggest I do:

first shot: ~ gcc -o foo -ggdb foo.c foo.c: In function ‘main’: foo.c:31:
error: ‘flippedPoint’ undeclared (first use in this function) foo.c:31: error:
(Each undeclared identifier is reported only once foo.c:31: error: for each
function it appears in.)

Typo fixed: s/flippedPoint/secondPoint

what's the output?

    
    
        "{1, 2}{-1, -2}"
    
    

EDIT: Yours is actually an interesting example, and you're right, i responded
to quick from the typo fix and didn't actually grok it.

But, actually we're both wrong... and right? The real answer turns out to be a
bit more complicated. In your example the copies are made (automatically) in
the caller (main) which actually passes a pointer to flipPoint. Try
disassembling your executable. You'll see what I mean.

~~~
mistercow
[Double posting because I was out of my edit window by the time I saw your
edit]

>But, actually we're both wrong... and right? The real answer turns out to be
a bit more complicated. In your example the copies are made (automatically) in
the caller (main) which actually passes a pointer to flipPoint. Try
disassembling your executable. You'll see what I mean.

I'm really not sure that what the assembly code does is relevant. First off,
once it's in assembly, the concepts of "caller" and "function" are gone
completely. There are structures that correspond to what compilers typically
emit when you define and call functions, but there is no "copy in the caller
and pass a pointer to the function". There's just "copy this data on the
stack, put the location into a register, and then jump to this location".

Furthermore, this is looking at implementation details, and what we're
concerned here with are the _abstract concepts_ of how these languages work.
If you look at the assembly, you're seeing how your compiler decided to handle
it. If you have optimization on, flipPoint is going to be inlined anyway. The
spec doesn't really care how the compiler achieves the result as long as it
does achieve the correct result. One compiler might have it copy before
jumping and pass a pointer, but another compiler could just as easily pass a
pointer before jumping and then have the copy made after the jump. You would
not know the difference.

But the way C _acts_ is as if the fields of the struct were being copied when
they were passed to the function.

------
lvh
How is this different from call-by-value, where all values are object
references?

~~~
masklinn
It's not, it's call-by-value-but-some-people-can't-accept-it

------
manojlds
Isn't this by definition call by value? The reference / binding is passed by
value. Changing the reference to point to something else will not make the
other reference to point to the same too.

~~~
jknupp
Call by value would mean that a copy of the value of the argument is passed to
the function without involving the original value at all. To say the binding
is passed by value is not useful, as all languages would then be considered
"call by value", since _something_ needs to be passed into the function, and
we can just call it a value.

~~~
viraptor
This argument is as old as call-by-... definitions, but... What python holds
in the variables are references to objects. Those are the values you're
passing, so it's call by value using this reasoning.

Some languages do actually hold the value itself (struct for example) in the
variable, so there you get a copy of the value (the struct contents). In
python you get the copy of a reference (which again, is the value held in a
variable).

------
skittles
I'm a C# developer who also programmed in Java in the past. C# and Java both
pass pointers by value (which is what Python does too). This is a very
important thing to learn when programming C# or Java. A method (or function)
in any of these languages can either manipulate the object that the reference
points to, or they can reassign the reference to a new object internally
(which will leave the original object alone).

------
adrusi
this is over complicating the model to avoid saying what for some reason
people are terrified to say: that objects are just pointers. when you pass an
object you are passing the value of a reference. it's not that scary

~~~
jknupp
That's confusing the language specification with one of its implementations.
In Jython, for example, objects are not "just pointers".

~~~
adrusi
no, they are still just pointers. they might be pointers to something fancier
than a struct of its instance variables and abstracted by java's object system
but in the end it's still a pointer

------
alphaBetaGamma
I have a C based mental model of what is happening. Can anyone comment on
whether it is correct?

In C terms, I think of all objects (including primitives such as numbers) as a
struct with a void* pointer that holds the actual data, and another field that
describes how to interpret the data: struct Obj { void* data; ObjDesc descr; }

Whenever you do objA=objB you create an new struct Obj with objA.data ==
objB.data. The same things happens when you pass an object to a function: you
create a copy of the Obj.

When you modify an Obj, two things can happen: if the Obj is immutable you
change where void* data points to: n1 = 4 n2 = b1 n1 = 5 ==> n1.data !=
n2.data

On the other hand, if Obj is mutable, than you don't change void* data, you
modify the memory pointed to by data: n1=[] n2=n1 n1.append(1) ==> n1.data ==
n2.data

Is this correct or is mental model going to bite me sometime?

~~~
void-star
This is really far off, actually.

I don't mean to criticize. I think the best advice is to read K&R C again.
And, as some other posters have suggested, take a look and at least a passing
understanding of the memory model and assembly code generated by C/C++
compilers.

You'll see, for instance, that type information is not stored as a field in a
C struct at all, it's purely a distinction for the compiler to use. A C
struct, indeed any type of data in C, is _just_data_ in memory. At the machine
level, there's no such thing as a type. Just registers, memory, and
instructions. The compiler uses type information to generate the right
instructions to handle the type.

And to clarify, type metadata _as_actual_data_ can exist in higher level
languages, but it's definitely not a C thing.

~~~
alphaBetaGamma
I was speaking of a model of how python does things, based on a C style
implementation. Not an explanation of how C works.

------
InclinedPlane
Python is a truly bizarre language in this regard. It's behavior is unusual
and similar only to a few other less well known niche languages such as C# and
Java.

~~~
rcthompson
I genuinely can't tell if you're trolling by calling Java a "less well known
niche language".

As for Python being bizarre, it's just call-by-value, as has been pointed out
elsewhere. The only arguably bizarre part is that all values must be pointers
to objects. But I target like that consistency. I prefer it to Java, where I
always have to think about whether a variable is an object pointer or a
primitive type.

~~~
calinet6
As far as I can tell, he was being entirely sarcastic.

------
pierrebai
Python is strictly a call-by-ref language. The author of the blog and many
commenter here seem confused. There are two causes:

1\. Some objects are immutable.

This makes some calls seem to be call-by-value, but they are not. A simple
look at the generated code makes this obvious. Integers, strings, tuples, ...
are passed by reference. It's just that you can't mutate the object being
passed.

2\. The behaviour of the assignment operator is different from most non-
functional language.

In Python, assignment never mutate values. It assign a new reference to the
'variable' (i.e. the scoped name). This explains clearly why in functions, you
can't mutate an immutable object even though it is passed by reference:
assignment merely rebind the argument name to a new value.

That is why when you want to mutate something in a function in Python, your
only recourse is to call a function on that object:

    
    
      i = 4
      s = 'George'
      l = [ 'me', 'you']
      foo (i, s, l)
    
      def foo(a, b, c):
        a = 3
        b = 'Mark'
        c.append( 42 )
        c = [ 2, 1 ]
    
      print(i, s, l)
      # prints 4, 'George', ['me', 'you', 42]

~~~
mistercow
While Python works by passing object references, it is not call-by-reference
as that term is usually understood. Call-by-reference means that assignment
within a function will be seen in the calling scope. That does not happen in
Python.

------
mattdeboard
Well, regardless of the call-by-x discussion, this is actually a really good
explanation of scope and state in Python. Code like:

    
    
      def grow(array):
        array.append(1)
    
      array = []
      grow(array)
    

leads to such needless complexity.

------
rmc
I highly recommend this site: <http://pythontutor.com/> It'll parse and
execute python code, including showing what variables are pointing to what
obects.

------
mistercow
Since you explained name binding anyway, a useful way to describe Python might
just be "call-by-binding".

------
tsuyoshi
I'm not too familiar with Python, but the semantics of Python described here
match every other language that I can think of (including C). Can anyone give
me an example of a language that is actually call-by-reference?

~~~
Jach
C++ supports call-by-reference (and also call-by-value), here's an example of
call-by-reference:

    
    
        #include <iostream>
        void swap(int &x, int &y) {
          int temp = x;
          x = y;
          y = temp;
        }
        int main() {
          int a = 3;
          int b = 4;
          std::cout << a; // 3
          std::cout << b; // 4
          swap(a, b);
          std::cout << a; // 4
          std::cout << b; // 3
        }

