why cannot assign to function call

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Jan 9 11:43:39 EST 2009


On Fri, 09 Jan 2009 08:30:46 -0700, Joe Strout wrote:

> That's correct.  The reference itself is passed in, not the variable (or
> expression) that held or generated the reference in the calling code.
> 
> This is no different from, in C, passing an integer:
> 
> void foo(int bar) {
>     bar = 42;
> }
> int baz = 0;
> foo(baz);
> 
> This doesn't change baz because, speaking precisely, baz wasn't passed
> to foo -- only the *value* of baz (i.e. 0) was passed to foo.

We can check whether bar and baz are the same thing, by printing their 
addresses:

#include<stdio.h>
void foo(int bar) {
  printf("\n The address of bar is %p ", &bar);
  bar = 42;
}

int main() {
        int baz = 0;
        printf("\n The address of baz is %p ", &baz);
        foo(baz);
        return 0;
}


When I do this, I get:

 The address of baz is 0xbfa72870
 The address of bar is 0xbfa72850

So we can agree that baz and bar are different entities. Now, would 
anyone like to take a small wager on what the equivalent code in CPython 
would print?


def foo(bar):
  print " The address of bar is %s " % id(bar)
  bar = 42

baz = 0
print " The address of baz is %s " % id(baz)
foo(baz)


When I execute this, I get

 The address of baz is 143599468
 The address of bar is 143599468

Python doesn't do the same thing as C. It actually passes the same value 
to the function, without copying it.

Why oh why do you keep insisting that Python is no different from C?


Let's try one more. In C:

#include <stdio.h>
#include <stdlib.h>

struct record {
  int x;
};

void mutate(struct record bar) {
  printf("\n The address of bar is %p ", &bar);
  bar.x = 0;
  printf("\n Inside: %d ", bar.x);
}

struct record baz;

int main(void) {
  baz.x = 1;
  printf("\n The address of baz is %p ", &baz);
  printf("\n Before: %d ", baz.x);
  mutate(baz);
  printf("\n After: %d ", baz.x);
  return 0;
}


gives output: 

 The address of baz is 0x80496fc
 Before: 1
 The address of bar is 0xbfb8f980
 Inside: 0
 After: 1


We can clearly see that baz and bar are different entities, and changes 
made to bar inside the function don't affect baz.

A Python equivalent:

class struct: pass

def mutate(bar):
  print " The address of bar is %d " % id(bar)
  bar.x = 0;
  print " Inside: %d " % bar.x

baz = struct()
baz.x = 1
print " The address of baz is %d " % id(baz)
print " Before: %d " % baz.x
mutate(baz)
print " After: %d " % baz.x


which gives output:

 The address of baz is 3085537420
 Before: 1
 The address of bar is 3085537420
 Inside: 0
 After: 0



Why oh why do you keep insisting that Python is no different from C?


-- 
Steven



More information about the Python-list mailing list