By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,501 Members | 1,660 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,501 IT Pros & Developers. It's quick & easy.

By value or by reference?

P: n/a
Hi all!

How does Python pass arguments to a function? By value or by reference?

Thanks,
Riccardo Rossi.
Jul 18 '05 #1
Share this Question
Share on Google+
36 Replies


P: n/a
Riccardo Rossi wrote:
Hi all!

How does Python pass arguments to a function? By value or by reference?

Thanks,
Riccardo Rossi.

By reference to an object....See the python tutorial.
Jul 18 '05 #2

P: n/a
"Riccardo Rossi" <ri***************@email.it> writes:
Hi all!

How does Python pass arguments to a function? By value or by reference?


IIRC, by reference. It uses a copy on write algorithm.

--
Godoy. <go***@ieee.org>
Jul 18 '05 #3

P: n/a
Roger Irwin wrote:
Riccardo Rossi wrote:
Hi all!

How does Python pass arguments to a function? By value or by reference?

Thanks,
Riccardo Rossi.

By reference to an object....See the python tutorial.


Wrong. Here is the difference between pass by reference and pass by
value to CS types:
def foo(a): a = 1 .... i = 10
foo(i)
print i


With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.

-Jonathan

Jul 18 '05 #4

P: n/a
Jonathan Ellis <jb*****@gmail.com> wrote:
...
By reference to an object....See the python tutorial.


Wrong. Here is the difference between pass by reference and pass by
value to CS types:
def foo(a): a = 1 ... i = 10
foo(i)
print i


With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.


....so you tell "CS types" it's pass-by-value, and they come right back
with

def bar(b): b.append(2)

z = []
bar(z)
print z

With pass-by-value, they'll say, z would still be []. However, since
what is passed is not just (a copy of) the value, but (a reference to)
the object itself, z is [2] instead.

The terminology problem may be due to the fact that, in python, the
value of a name is a reference to an object. So, you always pass the
value (no implicity copying), and that value is always a reference.

I find it simpler to explain as: the semantics of argument passing are
_exactly_ identical to that of assignment (binding) to a barename; you
can fruitfully see argument passing as local (bare) names of the called
function being assigned initial values by the caller (that's exactly
what happens, in practice). Now if you want to coin a name for that,
such as "by object reference", "by uncopied value", or whatever, be my
guest. Trying to reuse terminology that is more generally applied to
languages where "variables are boxes" to a language where "variables are
post-it tags" is, IMHO, more likely to confuse than to help.
Alex
Jul 18 '05 #5

P: n/a
Jonathan Ellis wrote:
Roger Irwin wrote:
Riccardo Rossi wrote:
How does Python pass arguments to a function? By value or by reference?


By reference to an object....See the python tutorial.


Wrong. Here is the difference between pass by reference and pass by
value to CS types:
> def foo(a): a = 1 ... > i = 10
> foo(i)
> print i
With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.


It remains 10 because integers are immutable, so the function
code cannot modify the caller's variable anyway. However, if
you pass a mutable variable, things look a little different:
def foo(a): a[0] = 1 .... i = [10]
foo(i)
print i

[1]

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #6

P: n/a
Riccardo Rossi wrote:
Hi all!

How does Python pass arguments to a function? By value or by reference?
Both...
Err, no, none.
Well...

*Short answer :*
args are passed by ref, but bindings are local.

*Long answer :*
You first need to understand what 'variables' in Python are. They are in
fact just a symbol referencing an object. Think of a Python 'variable'
as an entry in a dict, the name of the variable (the 'symbol') being the
key and the reference to the object being the value (AFAIK, this is
exactly what they are).

You also need to understand the difference between mutable and immutable
objects. Strings, numerics and tuples are immutables. Which means that
you can not change them. When doing :
s = "Hello "
s += "World"
.... you are not modifying the string object bound to s, but creating a
new string object and binding it to s.

Now for the "By Val/By Ref" stuff... well, try this :

def my_fun(my_arg):
print "in my_fun, before rebinding my_arg: my_arg = %s" % my_arg
my_arg = "42"
print "in my_fun, after rebinding my_arg: my_arg = %s" % my_arg

the_arg = "Life, the Universe, and Everything"

print "before call to my_fun: the_arg = %s" % the_arg
my_fun(the_arg)
print "after call to my_fun: the_arg = %s" % the_arg
You should have somthing like this :

before call to my_fun: the_arg = Life, the Universe, and Everything
in my_fun, before rebinding my_arg: my_arg = Life, the Universe, and
Everything
in my_fun, after rebinding my_arg: my_arg = 42
after call to my_fun: the_arg = Life, the Universe, and Everything

So what ? are we passing args by value ? Well, retry with :

def my_fun_2(my_arg_2):
print "in my_fun, before appending to my_arg_2: my_arg_2 = %s" %
my_arg_2
my_arg_2.append("42")
print "in my_fun, after appending to my_arg_2: my_arg_2 = %s" %
my_arg_2

the_arg_2 = ["Life, the Universe, and Everything"]

print "before call to my_fun_2: the_arg_2 = %s" % the_arg_2
my_fun_2(the_arg_2)
print "after call to my_fun_2: the_arg_2 = %s" % the_arg_2

and what do we get ?

before call to my_fun_2: the_arg_2 = ['Life, the Universe, and Everything']
in my_fun, before appending to my_arg_2: my_arg_2 = ['Life, the
Universe, and Everything']
in my_fun, after appending to my_arg_2: my_arg_2 = ['Life, the Universe,
and Everything', '42']
after call to my_fun_2: the_arg_2 = ['Life, the Universe, and
Everything', '42']

Argh ! So what ? Is it by val or by ref ?
Ok, let's try a third test :

def my_fun_3(my_arg_3):
print "in my_fun, before rebinding my_arg_3: my_arg_3 = %s" % my_arg_3
my_arg_3 = ["42"]
print "in my_fun, after rebinding my_arg_3: my_arg_3 = %s" % my_arg_3

the_arg_3 = ["Life, the Universe, and Everything"]

print "before call to my_fun_3: the_arg_3 = %s" % the_arg_3
my_fun_3(the_arg_3)
print "after call to my_fun_3: the_arg_3 = %s" % the_arg_3

An you get :
before call to my_fun_3: the_arg_3 = ['Life, the Universe, and Everything']
in my_fun, before rebinding my_arg_3: my_arg_3 = ['Life, the Universe,
and Everything']
in my_fun, after rebinding my_arg_3: my_arg_3 = ['42']
after call to my_fun_3: the_arg_3 = ['Life, the Universe, and Everything']

err... Time for some explanation ?-)

When you call a function with an arg, a "local variable" is created,
which references the object passed as the argument. (well... an entry
with the formal parameter name as key and a reference to the object
passed in is created in the 'local' dict).

So, rebinding this local symbol does not impact the binding in the
caller's namespace - because the symbol lives in another namespace.

*But* - and if the object referenced is mutable of course - modifying
the object in the function... well, just modifies the object, because
it's the *same* object that is bound to ('referenced by', if you prefer)
both symbols (the one in the caller's namespace and the one in the
function's namespace). So yes, the object *is* modified when the
function returns.

(Of course, doing anything to an immutable object is just rebinding the
symbol, so it won't never have any impact outside the function. So don't
expect to have a function having side-effects on strings, numerics and
tuples args. The good news being that this is not necessary, since the
only reason to do so would be to return multiple values, and Python can
already return multiple values.)
Does it make sens to you ?-)
Thanks,
Riccardo Rossi.


HTH
Bruno

(Ho, BTW, please read the fine manual - and this too :
http://starship.python.net/crew/mwh/...jectthink.html)

Jul 18 '05 #7

P: n/a
JCM
Jorge Godoy <go***@ieee.org> wrote:
"Riccardo Rossi" <ri***************@email.it> writes:
Hi all!

How does Python pass arguments to a function? By value or by reference?

IIRC, by reference. It uses a copy on write algorithm.


Copy-on-write is an optimization. It doesn't affect the semantics of
the laguage.
Jul 18 '05 #8

P: n/a
JCM
Oliver Fromme <ol**@haluter.fromme.com> wrote:
....
> > > > def foo(a): a = 1 > ...
> > > > i = 10
> > > > foo(i)
> > > > print i

>
> With pass-by-reference, i would now be 1. However, since python is
> pass-by-value, it remains 10. It remains 10 because integers are immutable, so the function
code cannot modify the caller's variable anyway. However, if
you pass a mutable variable, things look a little different:


It doesn't matter that integers are immutable. Rebinding formal
parameters cannot change variables in the callers scope.
def foo(a): a[0] = 1 ... i = [10]
foo(i)
print i

[1]


In this case, you're dereferencing the list (I'm using pointer-
terminolgy, but I'm still talking about the behavior of the language,
not its implemenation). You're basically modifying the object passed
into the function, not rebinding a variable.
Jul 18 '05 #9

P: n/a
Jorge Godoy wrote:
IIRC, by reference. It uses a copy on write algorithm.


Really? Where? I've heard theoretical rumblings about
that but didn't realized it had been added anywhere.

Andrew
da***@dalkescientific.com
Jul 18 '05 #10

P: n/a
Jonathan Ellis wrote:
By reference to an object....See the python tutorial.


Wrong. Here is the difference between pass by reference and pass by
value to CS types:


Actually it is a reference to an object being passed.
def foo(a): a = 1
...
i = 10
foo(i)
print i
With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.

def foo(a): .... print id(a)
.... i = 10
id(i) 168377924 foo(i)

168377924

With pass-by-value, the memory location of a would be different than the
memory location of i. However, since Python is pass-by-reference, it
remains the same. <wink>

Alex is right that trying to shoehorn Python into a "pass-by-reference"
or "pass-by-value" paradigm is misleading and probably not very helpful.
In Python every variable assignment (even an assignment of a small
integer) is an assignment of a reference. Every function call involves
passing the values of those references.
--
Michael Hoffman
Jul 18 '05 #11

P: n/a
JCM
Michael Hoffman <m.*********************************@example.com > wrote:
....
With pass-by-value, the memory location of a would be different than the
memory location of i. However, since Python is pass-by-reference, it
remains the same. <wink>
The memory location of the object is the same; the memory location of
the reference is different.
Alex is right that trying to shoehorn Python into a "pass-by-reference"
or "pass-by-value" paradigm is misleading and probably not very helpful.
In Python every variable assignment (even an assignment of a small
integer) is an assignment of a reference. Every function call involves
passing the values of those references.


I've given up expressing my opinion on the matter. Everyone here
seems to have a different notion of what "pass-by-reference" and
"pass-by-value" mean. It's funny--I've never run into trouble with
these terms before seeing these discussions on C.L.Py.
Jul 18 '05 #12

P: n/a
I've given up expressing my opinion on the matter. Everyone here
seems to have a different notion of what "pass-by-reference" and
"pass-by-value" mean. It's funny--I've never run into trouble with
these terms before seeing these discussions on C.L.Py.


It is because Python does it differently from most other languages, and
it doesn't fit the paradigms of "pass by value" or "pass by reference"
as already explained by Alex Martelli.

Python does name binding with references. That is, each reference is
given a name, but you cannot change data by assigning to a name; you can
only change what data that name points to. There are certain operations
that can be done with mutable objects and immutable objects, but that is
another discussion entirely.
There is not so much an argument, but there is a semantic "what the hell
is it doing" that is not being communicated properly. I am sure there
is a FAQ about this, but I don't have the link handy, and I can't quite
find the right incantation for Google.

- Josiah

Jul 18 '05 #13

P: n/a
JCM
Josiah Carlson <jc******@uci.edu> wrote:
I've given up expressing my opinion on the matter. Everyone here
seems to have a different notion of what "pass-by-reference" and
"pass-by-value" mean. It's funny--I've never run into trouble with
these terms before seeing these discussions on C.L.Py.
It is because Python does it differently from most other languages, and
it doesn't fit the paradigms of "pass by value" or "pass by reference"
as already explained by Alex Martelli.
It's really not that different. It's very similar to the way Java
handles objects, and how scheme does argument-passing.
Python does name binding with references. That is, each reference is
given a name, but you cannot change data by assigning to a name; you can
only change what data that name points to. There are certain operations
that can be done with mutable objects and immutable objects, but that is
another discussion entirely.
Yes. These two issues often get muddled together in discussions about
argument passing. Are you avoiding the term "variable"? Some don't
like to use it because they see Python as somehow fundamentally
different than other languages. I think the term fits nicely.
There is not so much an argument, but there is a semantic "what the hell
is it doing" that is not being communicated properly. I am sure there
is a FAQ about this, but I don't have the link handy, and I can't quite
find the right incantation for Google. - Josiah


Jul 18 '05 #14

P: n/a
Josiah Carlson <jc******@uci.edu> wrote:
I've given up expressing my opinion on the matter. Everyone here
seems to have a different notion of what "pass-by-reference" and
"pass-by-value" mean. It's funny--I've never run into trouble with
these terms before seeing these discussions on C.L.Py.


It is because Python does it differently from most other languages, and


Actually, where "real objects" are concerned (there's a slew of
exceptions for primitive builtin types such as int) Java has quite
similar semantics for both assignment and parameter passing. Python's
simpler: no exceptions. C#'s more complicated: besides the types that
are built-in exceptions you can also make user-defined types that are
also exceptions. But exceptions apart, the 'fundamental' semantics of
assignments and assignment passing is similar in all three languages.
Alex
Jul 18 '05 #15

P: n/a

[snip section about Java]

Indeed, I meant in reference to C, but I should have been more precise.
Python does name binding with references. That is, each reference is
given a name, but you cannot change data by assigning to a name; you can
only change what data that name points to. There are certain operations
that can be done with mutable objects and immutable objects, but that is
another discussion entirely.


Yes. These two issues often get muddled together in discussions about
argument passing. Are you avoiding the term "variable"? Some don't
like to use it because they see Python as somehow fundamentally
different than other languages. I think the term fits nicely.


In my mind, "variable" implies that the data is implicitly "variable" by
assignment, which is not the case in Python.

Underlying name binding in Python is a Python dictionary; a mapping of
keys to values, where keys are names, and values are pointers to actual
data (there are optimizations for local scopes that replace the
dictionary with a static table, but one could use a dictionary and it
would work the same).

As a result, an assignment in a scope is no more than doing doing an
assignment to a key/value pair in dictionary, with similar "hey, we're
just swapping pointers on assignment, not changing the data itself" (at
least in terms of the 'value' part of the key,value pair).
In a C-semantic pass by reference, you get the pointer to the actual
data, and when you assign to that pointer, you change the data itself.
In a C-semantic pass by value, you get a value with copy on write
semantics.

If what Python does is like Java, perhaps C# or what have you, great. It
is, however, different from the C semantic description of "pass by value",
"pass by reference", and the standard CS education definition of either.

- Josiah

Jul 18 '05 #16

P: n/a
In article <uQ**************@newsread3.news.pas.earthlink.net >,
Andrew Dalke <ad****@mindspring.com> wrote:
Jorge Godoy wrote:
IIRC, by reference. It uses a copy on write algorithm.


Really? Where? I've heard theoretical rumblings about
that but didn't realized it had been added anywhere.


I think this is a misimpression - the copy on write
part, I mean - that may go back to a discussion that
took place a year ago here, where someone energetically
but erroneously advocated that point of view.

Donn Cave, do**@u.washington.edu
Jul 18 '05 #17

P: n/a
In article <41***********************@news.free.fr>,
Bruno Desthuilliers <bd*****************@free.quelquepart.fr> wrote:
....
*Short answer :*
args are passed by ref, but bindings are local.

*Long answer :*
You first need to understand what 'variables' in Python are. They are in
fact just a symbol referencing an object. Think of a Python 'variable'
as an entry in a dict, the name of the variable (the 'symbol') being the
key and the reference to the object being the value (AFAIK, this is
exactly what they are).

You also need to understand the difference between mutable and immutable
objects. Strings, numerics and tuples are immutables. Which means that
you can not change them. When doing :
s = "Hello "
s += "World"
... you are not modifying the string object bound to s, but creating a
new string object and binding it to s.


Well, true enough for string, but not true for list for example.

Aside from this wretched wart on the language, as another followup
has already pointed out, you really don't need to distinguish
mutable vs. immutable to understand argument passing and variable
binding in Python.

If you write:
def f(a, b):
a = 5
b.flog(5)

.... it makes no difference whether either argument is mutable
or immutable. a becomes a different object notwithstanding,
and b.flog operates on the caller's original object whether flog
modifies anything or not. We tend to make this too complicated.

Donn Cave, do**@u.washington.edu
Jul 18 '05 #18

P: n/a
Josiah Carlson <jc******@uci.edu> wrote:
...
If what Python does is like Java, perhaps C# or what have you, great. It
is, however, different from the C semantic description of "pass by value",
"pass by reference", and the standard CS education definition of either.


C is also very simple, just like Python: C always does pass by value.
I.e., C always does implicit copy (on assignment or parameter passing),
just like Python never does.

So in C you ask explicitly when you want a reference (pointer) instead,
e.g. with &foo -- in Python you ask explicitly when you want a copy
instead, e.g. with copy.copy(foo). Two simple language, at opposite
ends of the semantics scale, but each consistent and clean. (Python
matches 4.5 of the 5 points which define "the spirit of C" according to
the latter's Standard's preface...!-).

[[ok, each has its warts -- e.g. C has arrays which mysteriously decay
into pointers instead of getting copied, Python has slices that make
copies instead of sharing part of the original sequence [or not; it
depends whether said sequence is a list or Numeric.array, sigh...] --
being human and being perfect are incompatible traits. But _mostly_
they have simplicity and consistency, everything explicit.]]

The key point is that, in both languages, a function's arguments are
just like local variables pre-initialized by the caller with assignment
statements. In both languages, if the function reassigns an argument
it's just playing with its own local variables, the caller is never in
any way affected by that. In both languages, there are other ways
except plain barename assignments to possibly "affect the caller" (in C
you basically need to have been passed a pointer, and dereference that
pointer or another pointer computed from the first by pointer
arithmetic; in Python you basically need to have been passed a mutable
object, and call mutating methods on that object). Again, in both cases
I see simplicity and consistency, everything pretty explicit...
Alex
Jul 18 '05 #19

P: n/a
JCM
Alex Martelli <al*****@yahoo.com> wrote:
....
C is also very simple, just like Python: C always does pass by value.
I.e., C always does implicit copy (on assignment or parameter passing),
just like Python never does. So in C you ask explicitly when you want a reference (pointer) instead,
e.g. with &foo -- in Python you ask explicitly when you want a copy
instead, e.g. with copy.copy(foo). Two simple language, at opposite
ends of the semantics scale, but each consistent and clean. (Python
matches 4.5 of the 5 points which define "the spirit of C" according to
the latter's Standard's preface...!-).


This is misleading. copy.copy does a smart, data-structure-aware copy
(not a deep copy, but exactly what copy.copy does differs among
datatypes). Parameter passing isn't about data structures; it's about
what an assignment statement means when you're assigning to a formal
parameter within a function (also possibly about some other things
like lazy evaluation), for example whether the argument list is a
declaration of new variables or just a set of aliases for other
pre-existing values (I don't say "variables" here because the value
passed in may be anonymous).
Jul 18 '05 #20

P: n/a
> The key point is that, in both languages, a function's arguments are
just like local variables pre-initialized by the caller with assignment
statements. In both languages, if the function reassigns an argument
it's just playing with its own local variables, the caller is never in
any way affected by that. In both languages, there are other ways
except plain barename assignments to possibly "affect the caller" (in C
you basically need to have been passed a pointer, and dereference that
pointer or another pointer computed from the first by pointer
arithmetic; in Python you basically need to have been passed a mutable
object, and call mutating methods on that object). Again, in both cases
I see simplicity and consistency, everything pretty explicit...


I agree with most everything you have said, though consider the pointer
vs. value of C to define the semantics of the passing. That is, if you
get a pointer in C, it is by reference. If you don't get a pointer, it
is by value.

I also agree that everything is pure and explicit in both languages, it
took me a few minutes mucking around with the interpreter my first time
to understand how Python deals with the base types.

I'm trying to point out that if you toss the standard C semantic
definition of "pass by value" and "pass by reference", by merely
pretending that the definitions have not been given in the history of
computer science, and just look at how Python does actual name binding
in namespaces/scopes, you can understand what Python does much better
than to get into a "Python does pass by reference" vs. "Python does pass
by value" argument.
- Josiah

Jul 18 '05 #21

P: n/a
On Mon, 18 Oct 2004 15:30:54 +0000, Riccardo Rossi wrote:
Hi all!

How does Python pass arguments to a function? By value or by reference?


Summarizing all of the arguments, it is "Pass by reference, by value".

The functions receive copies of the references, but the function receives
a new reference by value, not "the same reference" as it is in C++.

def something(a):
a = 11

immediately discards the passed-in reference with no affect on the caller.

This is never correct in Python:

somefunction() = "some value"

This is sort of "because" of the way Python bind names, and in another
sense, is the *cause* of the Python name binding behavior :-)
Jul 18 '05 #22

P: n/a
On Mon, 18 Oct 2004 18:04:58 +0200, al*****@yahoo.com (Alex Martelli) wrote:
Jonathan Ellis <jb*****@gmail.com> wrote:
...
> By reference to an object....See the python tutorial.


Wrong. Here is the difference between pass by reference and pass by
value to CS types:
>>> def foo(a): a = 1

...
>>> i = 10
>>> foo(i)
>>> print i


With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.


...so you tell "CS types" it's pass-by-value, and they come right back
with

def bar(b): b.append(2)

z = []
bar(z)
print z

With pass-by-value, they'll say, z would still be []. However, since
what is passed is not just (a copy of) the value, but (a reference to)
the object itself, z is [2] instead.

The terminology problem may be due to the fact that, in python, the
value of a name is a reference to an object. So, you always pass the
value (no implicity copying), and that value is always a reference.

I find it simpler to explain as: the semantics of argument passing are
_exactly_ identical to that of assignment (binding) to a barename; you
can fruitfully see argument passing as local (bare) names of the called
function being assigned initial values by the caller (that's exactly
what happens, in practice). Now if you want to coin a name for that,
such as "by object reference", "by uncopied value", or whatever, be my
guest. Trying to reuse terminology that is more generally applied to
languages where "variables are boxes" to a language where "variables are
post-it tags" is, IMHO, more likely to confuse than to help.

Maybe something like this can help elucidate the mechanism(s) of passing arguments?
(I.e., as a sort of automatic tuple formation from the arg list and unpacking it
into the locals indicated by the parameter name list)?
a = 1
b = 'two'
def foo(x,y): ... print 'x=%r, y=%r'%(x, y)
... def bar(*args): ... x, y = args
... print 'x=%r, y=%r'%(x, y)
... c = (a, b)
foo(a,b) x=1, y='two' foo(*c) x=1, y='two' bar(a,b) x=1, y='two' bar(*c)

x=1, y='two'

Regards,
Bengt Richter
Jul 18 '05 #23

P: n/a
"Riccardo Rossi" <ri***************@email.it> wrote in message news:<Ok*********************@news4.tin.it>...
Hi all!

How does Python pass arguments to a function? By value or by reference?


If you're familiar with C, think of it this way

/* Python function

def foo(arg1, arg2):
localA = arg1
localB = bar(arg2)
# ...

*/
object *foo(object *arg1, object *arg2) {
object *localA = arg1;
object *localB = bar(arg2);
/* ... */
}
Jul 18 '05 #24

P: n/a

On 2004 Oct 18, at 22:46, Josiah Carlson wrote:
...

I agree with most everything you have said, though consider the pointer
vs. value of C to define the semantics of the passing. That is, if you
get a pointer in C, it is by reference. If you don't get a pointer, it
is by value.
I disagree: you get the value of the pointer. If you assign to the
barename of the pointer, this has no effect on the caller.

void foo(int* x) {
x = 0;
}

the fact that x is a pointer makes no difference whatsoever: the x=0;
within function foo is just assigning to local variable 'x', without
any effect on the caller, just as if the signature was '(int x)'
instead.

"By reference" semantics, in e.g. Fortran, Visual Basic, Pascal, C++,
...., are normally taken to mean that the function can do:
x = 0;
i.e. assign to the barename of an argument, and thereby affect the
caller. In Fortran (traditionally) it's always that way (the language
definition supports both value/return and reference semantics, with
lots of strictures on what is semantically correct in order to ensure
both mechanisms work; in practice, implementations for the last 30+
years have used references, 99% of Fortran programmers are unaware of
the strictures, and get big surprises when an aggressive optimizer,
taking advantage of the constraints the programmers routinely violate,
turns their code into mush;-). In Pascal, defining an argument in the
signature as "x:integer" or "var x:integer" makes all the difference;
in Visual Basic, the adjectives Byval and Byref do; in C++, the
referencemarker ampersand ('int&x' in the signature); etc.

C has nothing like that. You can explicitly take the address of
something, you can pass (by value!) an address ('pointer'), you can
dereference an address -- and these are the mechanisms you can use to
get PAST the lack of byref parameters. The workarounds in Fortran for
the lack of byval parameters are sometimes even funnier: you see X+0
passed as the actual argument, for example, or sometimes X*1, in the
hope that this will make a copy of X and thereby preserve X from
modification (the interested reader can study the Fortran 66 and 77
manuals to see how this tricks have fared, standardswise... compilers
often are more accomodating than the standards, though in the Fortran
world optimization is SO crucial that this need not be so...).
[[similar tricks in Python are using L[:], L+[], or L*1, to get a copy
of L -- less forgivable in Python where list(L) does that cleanly,
explicitly and legibly, of course;-)]]

I also agree that everything is pure and explicit in both languages, it
took me a few minutes mucking around with the interpreter my first time
to understand how Python deals with the base types.

I'm trying to point out that if you toss the standard C semantic
definition of "pass by value" and "pass by reference", by merely
pretending that the definitions have not been given in the history of
computer science, and just look at how Python does actual name binding
in namespaces/scopes, you can understand what Python does much better
than to get into a "Python does pass by reference" vs. "Python does
pass
by value" argument.


I agree. But in C you cannot possibly do better than "C does pass by
value, and assigns by value [with an unfortunate hack regarding arrays
decaying to pointers]". The concept of passing by reference is needed
in other languages, but not in C (nor Python). "Pass by value"
normally (for most languages) implies a copy: once you realize that
Python doesn't do implicit copies (the +[], *1 and [:] hacks
notwithstanding, those ARE computing expressions after all) then 'pass
by value' is in fact just as applicable to Python -- the difference is
not in how arguments are passed, but in the fact that in Python a
name's value is ALWAYS a reference to an object, so the value (that is
passed) IS the reference (to the object), while in C variables are
little boxes with their value inside, so the value that is passed is a
copy of the box's contents (some of those boxes, known as pointers,
hold addresses...).
Alex

Jul 18 '05 #25

P: n/a
"Riccardo Rossi" <ri***************@email.it> writes:
How does Python pass arguments to a function? By value or by reference?


[Or maybe "by name", or even "by need" ?]

Don't take anyone's word for it. Check for yourself.

Here's a program that tells you the answer. Should be trivially
translatable to many other languages.

================================================== ======================
def passCheck(b):
b = 'new'

def doesThisLanguageBindByValue(language):
a = 'original'
b = a
b = 'new'
if a == 'original':
print "%s assigns by value" % (language)
else:
print "%s does not assigns by value" % (language)

a = 'original'
passCheck(a)
if a == 'original':
print "%s passes by value" % (language)
else:
print "%s does not pass by value" % (language)

doesThisLanguageBindByValue('Python')
================================================== ======================

Caveat: Once you've convinced yourself that the answer is "by value",
do notice that the values are references, so you can give the
impression that you have by-reference semantics, by passing or
assigning a mutable object and mutating it. But the _binding_
mechanism is most certainly "by value".
Jul 18 '05 #26

P: n/a
JCM <jo******************@myway.com> wrote:
Alex Martelli <al*****@yahoo.com> wrote:
...
C is also very simple, just like Python: C always does pass by value.
I.e., C always does implicit copy (on assignment or parameter passing),
just like Python never does.
So in C you ask explicitly when you want a reference (pointer) instead,
e.g. with &foo -- in Python you ask explicitly when you want a copy
instead, e.g. with copy.copy(foo). Two simple language, at opposite
ends of the semantics scale, but each consistent and clean. (Python
matches 4.5 of the 5 points which define "the spirit of C" according to
the latter's Standard's preface...!-).


This is misleading. copy.copy does a smart, data-structure-aware copy


I imagine you mean something like "type-aware" here. But I don't see
anything misleading here, nevertheless.
(not a deep copy, but exactly what copy.copy does differs among
datatypes). Parameter passing isn't about data structures; it's about
Some languages do use different parameter passing conventions depending
on the types involved, actually; I believe C# is an example. Most
languages do fortunately eschew such complications.
what an assignment statement means when you're assigning to a formal
parameter within a function (also possibly about some other things
....which in turn depends, also, on what assignment statements mean *in
general*. In C, a=b means (assuming the same datatype on both sides;
you can't ignore datatypes in C...): copy the bits that are in the "box"
named b, into the "box" named a. In Python, a=b means: attach the "tag"
a, to the same object to which the "tag" b is also attached right now.

The distinction is put in sharper evidence for some datatypes than for
others -- clearest with a C struct:

typedef struct {
int x, y;
} xy;
xy a = {1, 2};
xy b = {3, 4};

wrt a roughly equivalent Python class

class xy:
def __init__(self, x, y): self.x, self.y = x, y
a = xy(1, 2)
b = xy(3, 4)

After a=b followed by b.x=5, what's a.x? In C, it's still 3, because
the assignment was a copy of b's bits at that time; in Python, it's 5,
because the assignment just made names a and b refer to the same object.

And exactly the same thing applies if you have a function, and pass b in
as its actual argument:

void foo(xy c) { c.x = 6; }

vs, in Python:

def foo(c): c.x = 6

once you call foo(b), in each language, it's just as if there had been
an assignment c=b by the rules of the respective language, followed by
the c.x=6 part. Just like above, in C b.x is unaffected (because the
assignment, resp. the parameter passing, did a copy); just like above,
in Python b.x is now 6 (because the assignment, resp. the parameter
passing, just gave one more name to the same object, without copies).

The two languages behave exactly the same if a function assigns to a
formal parameter's name, rather than (e.g.) to a field thereof:

void bar(xy d) { xy e = {7,8}; d = e; }

vs

def bar(d): d = xy(7, 8)

in each language, after you call bar(b), the value of b is totally
unaffected by the fact that the function assigns to its formal argument;
just like it would be by two back to back assignments such as
d = b;
d = e;
no effect on the value of b in either language.
like lazy evaluation), for example whether the argument list is a
declaration of new variables or just a set of aliases for other
pre-existing values (I don't say "variables" here because the value
passed in may be anonymous).


That concept of "alias" is in fact somewhat alien to both C and Python.
A "new variable" in C is a new box where bits may be copied; a "new
variable" in C is a new label which can attached to objects.

Thus, passing arguments in each language has exactly the same effect as,
in the same language, having a bunch of new variables -- which in C
means a bunch of new boxes filled with bits (copied) from somewhere, in
Python means a bunch of new labels attached to objects from somewhere.

That's very different from Fortran, where such "aliasing" is indeed the
norm in parameter passing (but not in assignment; differently from C and
Python, Fortran has very different semantics for assignment and
parameter passing). In that case, a subroutine assigning to the
barename of one of its formal arguments can indeed affect the caller,
iff the caller had passed in a variable (or array item) as the actual
argument corresponding. It need not be call by reference (at least not
as far back as Fortran IV): the language was quite careful to constrain
the valid operations so that an implementation was free to either use a
reference _OR_ copy values on subroutine entry and exit, for
optimization purposes. Most Fortran programmers didn't really
understand that part very well, but here's an example:

SUBROUTINE INCBOTH(I, J)
I = I + 1
J = J + 2
END

this is valid Fortran. However, CALL INCBOTH(MU,MU) is invalid (though
barely any compiler/linker could diagnose this!) and the effects on MU
are undefined. In practice all compilers I've used would increment MU
by 3, but it would be perfectly valid to increment it by just 1 _or_ 2
(the compiler can choose to copy MU to I and J on entry, and I and J to
MU on exit, in either order) or even, I believe, to crash the program.

((These constraints on the programmer mean more freedom for the compiler
to optimize the snot out of the code, and that was traditionally a prime
consideration in Fortran. A hypothetical example where using
value/return might optimize things would be with a machine full of
registers and addressability only of memory, not of registers, and
perhaps some mechanism such as sliding register windows to optimize
parameter passing in registers. If Fortran HAD to use pass-by-reference
it could not optimize things by keeping all of MU, I and J in registers
(as we assumed registers to not be addressable -- most machines are that
way, though I recall some delightful exceptions where "registers" in
fact had addresses and could thus be used fully interchangeably with
memory locations, such as some HP and TI minicomputers); with the
ability to pass by copy-on-entry, copy-on-exit, everything can stay in
registers here, just as it could for a pass-by-value language.))

So, back to our muttons, I don't see anything misleading about anything
I said. Terminology apart, it doesn't seem we have disagreements; but
terminology does have some importance, and trying to shoehorn not fully
appropriate terminology may help confuse somebody's thinking, at times.
Alex
Jul 18 '05 #27

P: n/a
Donn Cave wrote:
In article <41***********************@news.free.fr>,
Bruno Desthuilliers <bd*****************@free.quelquepart.fr> wrote:
...
*Short answer :*
args are passed by ref, but bindings are local.

*Long answer :*
You first need to understand what 'variables' in Python are. They are in
fact just a symbol referencing an object. Think of a Python 'variable'
as an entry in a dict, the name of the variable (the 'symbol') being the
key and the reference to the object being the value (AFAIK, this is
exactly what they are).

You also need to understand the difference between mutable and immutable
objects. Strings, numerics and tuples are immutables. Which means that
you can not change them. When doing :
s = "Hello "
s += "World"
... you are not modifying the string object bound to s, but creating a
new string object and binding it to s.

Well, true enough for string, but not true for list for example.


I may not have made clear enough that this consideration only applied to
immutable objects...

Aside from this wretched wart on the language, as another followup
has already pointed out, you really don't need to distinguish
mutable vs. immutable to understand argument passing and variable
binding in Python.

If you write:
def f(a, b):
a = 5
b.flog(5)

... it makes no difference whether either argument is mutable
or immutable. a becomes a different object notwithstanding,
and b.flog operates on the caller's original object whether flog
modifies anything or not. We tend to make this too complicated.


Perhaps, but still there's the case of

def foo_list(bar_list):
bar_list += ['42']

which behave quite differently from

def foo_str(bar_str):
bar_str += '42'

My 2 cents
Bruno
Jul 18 '05 #28

P: n/a
Josiah Carlson <jc******@uci.edu> wrote:
I agree with most everything you have said, though consider the pointer
vs. value of C to define the semantics of the passing. That is, if you
get a pointer in C, it is by reference. If you don't get a pointer, it
is by value.


I disagree: you get the value of the pointer. If you assign to the
barename of the pointer, this has no effect on the caller.


[snip the remainder of the email]

Sounds good. Now with the semantic arguments out of the way, is there a
link where the equivalent of what was just said is available in the
documentation?

If yes, great. If not, perhaps what has been discussed should be
slimmed down and inserted into the FAQ so that future generations don't
need to rehash this conversation.


Sure, but it's a vain hope -- 2 out of 3 questions asked here ARE about
stuff well covered in the FAQ, anyway.
Alex
Jul 18 '05 #29

P: n/a
Jacek Generowicz <ja**************@cern.ch> wrote:
...
Here's a program that tells you the answer. Should be trivially
translatable to many other languages.

================================================== ======================
def passCheck(b):
b = 'new'

def doesThisLanguageBindByValue(language):
a = 'original'
b = a
b = 'new'
if a == 'original':
print "%s assigns by value" % (language)
else:
print "%s does not assigns by value" % (language)


Can you give some examples of languages which would end up in the else
branch? I think that with a suitably perverse operator= I might be able
to imitate this weird effect in C++, but then I think I'd have to make
the 'b = a' a copy ctor instead of an assignment (or get to such levels
of perversion that even my once-C++-addled mind reels at...;-).
Alex
Jul 18 '05 #30

P: n/a
On Tue, 19 Oct 2004 21:15:21 +0200, al*****@yahoo.com (Alex Martelli) wrote:
Josiah Carlson <jc******@uci.edu> wrote:
> > I agree with most everything you have said, though consider the pointer
> > vs. value of C to define the semantics of the passing. That is, if you
> > get a pointer in C, it is by reference. If you don't get a pointer, it
> > is by value.
>
> I disagree: you get the value of the pointer. If you assign to the
> barename of the pointer, this has no effect on the caller.


[snip the remainder of the email]

Sounds good. Now with the semantic arguments out of the way, is there a
link where the equivalent of what was just said is available in the
documentation?

If yes, great. If not, perhaps what has been discussed should be
slimmed down and inserted into the FAQ so that future generations don't
need to rehash this conversation.


Sure, but it's a vain hope -- 2 out of 3 questions asked here ARE about
stuff well covered in the FAQ, anyway.

I keep thinking there should be a tech fix for part of this problem. E.g.,
if interactive python help supported help(faqtopic='whatever') and that
automatically used urllib to search the latest faq (caching stuff perhaps)
and produced a topic-oriented HTML page with links to likely faq items, and
started a browser to display it ...
Hm, sounds like google with a site restriction. Maybe faq should live on
faq.python.org and help(faqtopic='...') could leverage that?

Anyway, the other part is feeding good stuff like your posted explanations
into the faq. I keep thinking a little posting markup of some sort could
make automated harvesting of c.l.py archives for faq snippets possible.

Regards,
Bengt Richter
Jul 18 '05 #31

P: n/a
al*****@yahoo.com (Alex Martelli) writes:
Jacek Generowicz <ja**************@cern.ch> wrote:
...
Here's a program that tells you the answer. Should be trivially
translatable to many other languages.

================================================== ======================
def passCheck(b):
b = 'new'

def doesThisLanguageBindByValue(language):
a = 'original'
b = a
b = 'new'
if a == 'original':
print "%s assigns by value" % (language)
else:
print "%s does not assigns by value" % (language)
Can you give some examples of languages which would end up in the else
branch?


Sure. Here it is in C++:

================================================== ======================
#include <iostream>
#include <string>

void passCheck(std::string& b) {
b = "new";
}

void doesThisBindByValue() {
std::string a = "original";
std::string& b = a;
b = "new";
if (a == "original") {
std::cout << "by value" << std::endl;
} else {
std::cout << "NOT by value" << std::endl;
}

a = 1;
passCheck(a);
if (a == "original") {
std::cout << "by value" << std::endl;
} else {
std::cout << "NOT by value" << std::endl;
}
}

int main() {

doesThisBindByValue();

return 0;
}
================================================== ======================
I think that with a suitably perverse operator= I might be able
to imitate this weird effect in C++, but then I think I'd have to make
the 'b = a' a copy ctor instead of an assignment (or get to such levels
of perversion that even my once-C++-addled mind reels at...;-).


No need for such horrors. Just declare the variables to be references
.... and then you really do get bind-by-reference. It does exactly what
is says on the tin (unusual for C++, I know :-).
Jul 18 '05 #32

P: n/a
Jacek Generowicz <ja**************@cern.ch> wrote:
...
def doesThisLanguageBindByValue(language):
a = 'original'
b = a
b = 'new'
if a == 'original':
print "%s assigns by value" % (language)
else:
print "%s does not assigns by value" % (language)
... Can you give some examples of languages which would end up in the else
branch?
Sure. Here it is in C++:

... std::string a = "original";
std::string& b = a;


Ah, references, of course. And you need to make the two "b =" bits
drastically different in meaning, taking advantage of the fact that C++
overloads = to mean both initialization/construction and assignment;
that's not quite cheating but it sure bends the rules;-).

And after all this, the message "C++ does not assign by value" is false,
because it sure does, under many (most!-) circumstances. You'd need to
rephrase this as "under at least some circumstances, C++ does assign
not-by-value" or the like.

To remove the need to bend the rules, and have both "b =" be
assignments, you do need a peculiar type for b, such as (untested and
I'm rusty in C++, so take it w/a grain of salt):

class sly {
private:
std::string *p;
public:
sly() { p=0; }
std::string& operator=(std::string& x) {
if(p) (*p)=x;
else p=&x;
}
};

Here, the first assignment to b (declared as 'sly b;') follows the else
branch of operator=, initializing p; following ones follow the if
branch, altering whatever p is holding on to.
((Not sure operator= as written will accept an '= "new";' assignment,
but if not that could be easily cured by overloading operator= with a
variant taking a const std::string&)).

OK, so there are languages which have reference-variables or let you
build such beasts -- as I recall the first one was Algol 68. But
"(language) does not assign by value" should be true only for languages
that do NOT assign by value, as opposed to ones which may have several
kinds of assignments...
Alex
Jul 18 '05 #33

P: n/a
al*****@yahoo.com (Alex Martelli) writes:
Jacek Generowicz <ja**************@cern.ch> wrote:
...
> def doesThisLanguageBindByValue(language):
> a = 'original'
> b = a
> b = 'new'
> if a == 'original':
> print "%s assigns by value" % (language)
> else:
> print "%s does not assigns by value" % (language) ... Can you give some examples of languages which would end up in the else
branch?
Sure. Here it is in C++:

...
std::string a = "original";
std::string& b = a;


Ah, references, of course.


Well, the original question _was_ (I prapharse) "by *reference*, or by
value?". Given that C++ allows you to choose, why not choose?
And you need to make the two "b =" bits drastically different in
meaning,
_I_ don't. That C++ choses to do so, is a different matter. (Hence my
earlier comment about C++ doing exactly what it says on the tin being
rather rare :-)
taking advantage of the fact that C++ overloads = to mean both
initialization/construction and assignment; that's not quite
cheating but it sure bends the rules;-).
I'm just using the surface syntax provided by C++. Don't blame me for
C++ being a complete mess :-)
And after all this, the message "C++ does not assign by value" is false,
because it sure does, under many (most!-) circumstances.
The relative frequency is a function of how often the programmer
choses to use "&".
You'd need to rephrase this as "under at least some circumstances,
C++ does assign not-by-value" or the like.
Which is why I _did_ rephrase the message in the C++ example :-0
OK, so there are languages which have reference-variables


Exactly. And Python is not one of them.
Jul 18 '05 #34

P: n/a
Jacek Generowicz <ja**************@cern.ch> writes:
Well, the original question _was_ (I prapharse) "by *reference*, or by
value?". Given that C++ allows you to choose, why not choose?


.... and if I had bothered to read the thread title I could have said
that the original question was _exactly_ "By value or by reference?".

:-)
Jul 18 '05 #35

P: n/a
> > > By reference to an object....See the python tutorial.

Wrong. Here is the difference between pass by reference and pass by
value to CS types:
>> def foo(a): a = 1 ...
>> i = 10
>> foo(i)
>> print i


With pass-by-reference, i would now be 1. However, since python is
pass-by-value, it remains 10.


...so you tell "CS types" it's pass-by-value, and they come right back
with

def bar(b): b.append(2)

z = []
bar(z)
print z

With pass-by-value, they'll say, z would still be []. However, since
what is passed is not just (a copy of) the value, but (a reference to)
the object itself, z is [2] instead.


It really depends on what you claim to be passed by value. In Python,
objects are passed by reference, but references are passed by value. So
one may say that z is being passed by value, since what is passed is a
copy of the reference. With that in mind, one may correctly say that
Python always do pass-by-value, and correctly say that it always do
pass-by-reference.

Here is an article presenting the issue in more detail (much more :-):

http://www-106.ibm.com/developerwork...y/j-passbyval/
The terminology problem may be due to the fact that, in python, the
value of a name is a reference to an object. So, you always pass the
value (no implicity copying), and that value is always a reference.

[...]

That's it.

--
Gustavo Niemeyer
http://niemeyer.net
Jul 18 '05 #36

P: n/a
Gustavo Niemeyer <ni******@conectiva.com> wrote:
...
It really depends on what you claim to be passed by value. In Python,
objects are passed by reference, but references are passed by value. So
one may say that z is being passed by value, since what is passed is a
copy of the reference. With that in mind, one may correctly say that
Python always do pass-by-value, and correctly say that it always do
pass-by-reference.
That's my point, even though it's argued the other way 'round, that
neither is correct, given the usual connotations of these terms.

Here is an article presenting the issue in more detail (much more :-):

http://www-106.ibm.com/developerwork...y/j-passbyval/
The terminology problem may be due to the fact that, in python, the
value of a name is a reference to an object. So, you always pass the
value (no implicity copying), and that value is always a reference.

[...]

That's it.


Right. And in common use, pass-by-value and -by-reference are thought
to imply something else. I wonder how Java deals with it, since (except
for some primitive types like int) it's just the same mechanism as
Python's; being widely used and academically acceptable it must have
found a satisfactory way to explain this, one would hope.
Alex
Jul 18 '05 #37

This discussion thread is closed

Replies have been disabled for this discussion.