Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Finding the instance reference of an object

43 views
Skip to first unread message

Astley Le Jasper

unread,
Oct 16, 2008, 10:01:13 AM10/16/08
to
Sorry for the numpty question ...

How do you find the reference name of an object?

So if i have this

bob = modulename.objectname()

how do i find that the name is 'bob'

Carsten Haese

unread,
Oct 16, 2008, 10:52:46 AM10/16/08
to

Why do you need to find that? You know that its name is 'bob'.

--
Carsten Haese
http://informixdb.sourceforge.net

Michele Simionato

unread,
Oct 16, 2008, 10:57:18 AM10/16/08
to

Astley Le Jasper

unread,
Oct 16, 2008, 11:04:23 AM10/16/08
to

I'm creating mulitple instances, putting them in a list, iterating
through the list to send them to some functions where process them
with some instance specific parameters. Something along the lines of:

bob = someobject()
harry = someobject()
fred = someobject()

parameterdict = {'bob':(0,1,2),'harry':(3,4,5),'fred':(6,7,8)}
people_list = (bob, harry, fred)

for person in people_list:
add_parameters(person)

def add_parameters(person)
mytuple = parameterdict[??????instance.name????]
person.x = mytuple[0]
person.y = mytuple[1]
person.z = mytuple[2]

... alternatively there is probably a very much easier way of doing
it.

Steven D'Aprano

unread,
Oct 16, 2008, 12:04:10 PM10/16/08
to
On Thu, 16 Oct 2008 08:04:23 -0700, Astley Le Jasper wrote:

> I'm creating mulitple instances, putting them in a list, iterating
> through the list to send them to some functions where process them with
> some instance specific parameters. Something along the lines of:
>
> bob = someobject()
> harry = someobject()
> fred = someobject()
>
> parameterdict = {'bob': (0,1,2), 'harry': (3,4,5), 'fred': (6,7,8)}
> people_list = (bob, harry, fred)
>
> for person in people_list:
> add_parameters(person)
>
> def add_parameters(person)
> mytuple = parameterdict[??????instance.name????]
> person.x = mytuple[0]
> person.y = mytuple[1]
> person.z = mytuple[2]
>
> ... alternatively there is probably a very much easier way of doing it.


Assuming that someobject() objects are hashable, you can do this:

# use the objects themselves as keys, not their names


parameterdict = {bob: (0,1,2), harry: (3,4,5), fred: (6,7,8)}

people_list = [bob, harry, fred]

but of course that doesn't work if someobject() items aren't hashable
(say, lists or dicts).

But in my opinion, this is probably the best way (untested):

def add_parameters(person, x, y, z):
# note we don't use any global variables
person.x = x
person.y = y
person.z = z

parameters = [(0,1,2), (3,4,5), (6,7,8)]
people = [bob, harry, fred]
for person, args in zip(people, parameters):
add_parameters(person, *args)

--
Steven

Diez B. Roggisch

unread,
Oct 16, 2008, 12:53:29 PM10/16/08
to
Astley Le Jasper schrieb:

Why not simply do

bob = someobject(0, 1, 2)

?

Diez

Larry Bates

unread,
Oct 16, 2008, 12:59:45 PM10/16/08
to

Short answer is that you can't. This because Python's names (bob) are bound to
objects (modulename.objectname()). They are NOT variables as they are in
"other" programming languages. It is perfectly legal in Python to bind multiple
names to a single object:

a=b=c=modulename.objectname()

a, b, and c all point to the same object. An object can have an unlimited
number of names bound to it. This is one of the most difficult concepts for
many beginning Python programmers to understand (I know I had a difficult time
at first). It is just not how we taught ourselves to think about "variables"
and you can write quite a lot of Python treating the names you bind to objects
like they were "variables".

To accomplish what you want, put your instances in a dictionary.

instances = {}
instances['bob'] = modulename.objectname()
instances['joe'] = modulename.objectname()
.
.
.

Then you can reference them as:

instances[name]

and/or you can pass the name in as an argument to the __init__ method of
objectname so that it can "hold" the name of the dictionary key that references
it (good for debugging/logging).

-Larry

Joe Strout

unread,
Oct 16, 2008, 1:24:28 PM10/16/08
to Python List
On Oct 16, 2008, at 10:59 AM, Larry Bates wrote:

>> how do i find that the name is 'bob'
>
> Short answer is that you can't. This because Python's names (bob)
> are bound to objects (modulename.objectname()). They are NOT
> variables as they are in "other" programming languages.

Which other programming languages? I've never seen an OOP language
that didn't work the same way as Python.

However, 'bob' here really is a variable. It's a variable whose value
(at the moment) is a reference to some object.

> It is perfectly legal in Python to bind multiple names to a single
> object:
>
> a=b=c=modulename.objectname()

Right -- three variables (a, b, and c) that all have the same value,
i.e. all refer to the same object. There's nothing more mysterious
here than

i=j=k=42

where i, j, and k all have the same value. (The OP's question would
be like asking "what is the name of the variable referring to 42? And
while you might, in theory, be able to produce a list of all such
variables by trolling through the Python's internals, it's a bit of a
silly thing to do.)

> a, b, and c all point to the same object. An object can have an
> unlimited number of names bound to it. This is one of the most
> difficult concepts for many beginning Python programmers to
> understand (I know I had a difficult time at first). It is just not
> how we taught ourselves to think about "variables" and you can write
> quite a lot of Python treating the names you bind to objects like
> they were "variables".

Well, they are variables. I'm not quite grasping the difficulty
here... unless perhaps you were (at first) thinking of the variables
as holding the object values, rather than the object references. That
is indeed something important to grasp, since it explains why if you do

a = b # where b was some object with an attribute 'foo'...
a.foo = 42

...you now find that b.foo is 42 too. Nothing mysterious once you
realize that the value of a and b is a reference to some object that
has a "foo" attribute.

Not sure if all this was helpful to anyone, but I hope so!

Best,
- Joe

Astley Le Jasper

unread,
Oct 16, 2008, 1:25:05 PM10/16/08
to

Because that was pseudo code to demonstrate what I was trying to
achieve. The parameters are more complicated than that.

Astley Le Jasper

unread,
Oct 16, 2008, 1:25:58 PM10/16/08
to
Thanks for all the responses. That helps.

Ta

ALJ

Aaron "Castironpi" Brady

unread,
Oct 16, 2008, 2:51:43 PM10/16/08
to
On Oct 16, 12:25 pm, Astley Le Jasper <Astley.lejas...@gmail.com>
wrote:

> Thanks for all the responses. That helps.
>
> Ta
>
> ALJ

If you're sure it's unique, why not just scan through the pairs in
locals()?

for k, v in locals():
if v is the_object_im_looking_for:
name_im_looking_for= k

This method can sometimes return more than one name, due to the
variable ordering of objects in dictionaries.

Steven D'Aprano

unread,
Oct 16, 2008, 9:30:22 PM10/16/08
to
On Thu, 16 Oct 2008 11:24:28 -0600, Joe Strout wrote:

> On Oct 16, 2008, at 10:59 AM, Larry Bates wrote:
>
>>> how do i find that the name is 'bob'
>>
>> Short answer is that you can't. This because Python's names (bob) are
>> bound to objects (modulename.objectname()). They are NOT variables as
>> they are in "other" programming languages.
>
> Which other programming languages? I've never seen an OOP language that
> didn't work the same way as Python.
>
> However, 'bob' here really is a variable. It's a variable whose value
> (at the moment) is a reference to some object.


Traditionally, a "variable" is a named memory location.

The main objection I have to using "variable" to describe Python name/
value bindings is that it has connotations that will confuse programmers
who are familiar with C-like languages. For example:

def inc(x):
x += 1

n = 1
inc(n)
assert n == 2

Why doesn't that work? This is completely mysterious to anyone expecting
C-like variables.

At this point people will often start confusing the issue by claiming
that "all Python variables are pointers", which is an *implementation
detail* in CPython but not in other implementations, like PyPy or Jython.

Or people will imagine that Python makes a copy of the variable when you
call a function. That's not true, and in fact Python explicitly promises
never to copy a value unless you explicitly tell it to, but it seems to
explain the above, at least until the programmer starts *assuming* call-
by-value behaviour and discovers this:

def inc(alist):
alist += [1] # or alist.append(1) if you prefer
return alist

a = [1, 2, 3]
b = inc(a)
assert a == [1, 2, 3]

Are functions call by value or call by reference???

(Answer: neither. They are call by name.)


I myself often talk about variables as shorthand. But it's a bad habit,
because it is misleading to anyone who thinks they know how variables
behave, so when I catch myself doing it I fix it and talk about name
bindings. Noobs might not know what that means, but that's a feature, not
a bug, because it gets them paying attention instead of making faulty
assumptions.

Of course, you're entitled to define "variable" any way you like, and
then insist that Python variables don't behave like variables in other
languages. Personally, I don't think that's helpful to anyone.

[snip]


> Well, they are variables. I'm not quite grasping the difficulty here...
> unless perhaps you were (at first) thinking of the variables as holding
> the object values, rather than the object references.

But that surely is what almost everyone will think, almost all the time.
Consider:

x = 5
y = x + 3

I'm pretty sure that nearly everyone will read it as "assign 5 to x, then
add 3 to x and assign the result to y" instead of:

"assign a reference to the object 5 to x, then dereference x to get the
object 5, add it to the object 3 giving the object 8, and assign a
reference to that result to y".

Of course that's what's really happening under the hood, and you can't
*properly* understand how Python behaves without understanding that. But
I'm pretty sure few people think that way naturally, especially noobs.
References are essentially like pointers, and learning pointers is
notoriously difficult for people. Python does a magnificent job of making
references easy, but it does so by almost always hiding the fact that it
uses references under the hood. That's why talk about variables is so
seductive and dangerous: Python's behaviour is *usually* identical to the
behaviour most newbies expect from a language with "variables".

--
Steven

Steven D'Aprano

unread,
Oct 16, 2008, 9:30:30 PM10/16/08
to
On Thu, 16 Oct 2008 11:51:43 -0700, Aaron \"Castironpi\" Brady wrote:

> If you're sure it's unique, why not just scan through the pairs in
> locals()?
>
> for k, v in locals():
> if v is the_object_im_looking_for:
> name_im_looking_for= k
>
> This method can sometimes return more than one name, due to the variable
> ordering of objects in dictionaries.

Because:

(1) in general, objects can have no name at all, or multiple names, so
this won't work in general (although it may work in a specific case);

(2) it's awfully inefficient if you are doing it a lot; and

(3) even if it works and you can afford to pay the cost, it is almost
certainly the Wrong Way to solve the problem at hand.


--
Steven

Aaron "Castironpi" Brady

unread,
Oct 16, 2008, 10:38:27 PM10/16/08
to
On Oct 16, 8:30 pm, Steven D'Aprano <st...@REMOVE-THIS-

In fact, what's more called-for, is a mapping in reverse:

name_im_looking_for= lookup[ the_object_im_looking_for ]

You'll just have to modify it in parallel with your local variables,
which is a (yet another) bad sign.

Terry Reedy

unread,
Oct 16, 2008, 10:39:25 PM10/16/08
to pytho...@python.org
Astley Le Jasper wrote:

> I'm creating mulitple instances, putting them in a list, iterating
> through the list to send them to some functions where process them
> with some instance specific parameters. Something along the lines of:
>
> bob = someobject()
> harry = someobject()
> fred = someobject()
>
> parameterdict = {'bob':(0,1,2),'harry':(3,4,5),'fred':(6,7,8)}
> people_list = (bob, harry, fred)
>
> for person in people_list:
> add_parameters(person)
>
> def add_parameters(person)
> mytuple = parameterdict[??????instance.name????]
> person.x = mytuple[0]
> person.y = mytuple[1]
> person.z = mytuple[2]

If you want an object to have a 'personal' name, give it a name
attribute, just like python does to modules, classes, and functions.

class someob():
def __init__(self,name):
self.name = name

people = {someob('bob'), someob('harry'), someob('fred')
...
def add_param(person):
mytuple = parameterdict[person.name]
...

Larry Bates

unread,
Oct 16, 2008, 11:00:59 PM10/16/08
to

Sorry Joe, but I respectfully disagree about "not being mysterious". I've been
on this list for about 8 years and this question/issue comes up EVERY week with
newbies. Python names are just not variables in the traditional sense. If they
were then:

a=b=c=[42]

would create three independent variables that each contained a list with a
single element of 42. That is not what Python does and just about every newbie
gets bitten by that fact at least once.

ow many posts have a read here where people do things like:

a = [1,2,3,4,5]
b = a
b.append(6)

and can't figure out why a now contains [1,2,3,4,5,6]?

Without fail they thought that b = a copied the contents of a into b. That is,
they thought of a and b as variables that "hold" values. Now the term
"variables" may mean something different to you than most of the other newbies
that frequent this list, but they all (including me when I first started) miss
the subtilety of the name/value bindings at first (but boy are they beautiful
when you finally see the light). Perhaps you were lucky and were able to grasp
this quite powerful concept more easily than most of us.

I think this is one of the most difficult concepts about Python to grasp for
people coming from VB, C, Fortran, Cobol (oops showed my age there), etc. We
trained our minds to treat "variables" like named buckets (or memory locations).
Even the OP here wants to interrogate the object in the bucket and coerce it
into giving him the bucket (variable) name.

The problem, as Steven so eloquently shows in a separate post, is that is is
hard to talk about names that are bound to objects. So we fall back into
familiar language and use "variable" which confuses a lot of newbies because
they have preconceived notion about what a "variable" is and what it does.

Regards,
Larry

Message has been deleted

Joe Strout

unread,
Oct 16, 2008, 11:19:28 PM10/16/08
to Python List
On Oct 16, 2008, at 7:30 PM, Steven D'Aprano wrote:

>> However, 'bob' here really is a variable. It's a variable whose
>> value
>> (at the moment) is a reference to some object.
>
> Traditionally, a "variable" is a named memory location.

Agreed.

> The main objection I have to using "variable" to describe Python name/
> value bindings is that it has connotations that will confuse
> programmers
> who are familiar with C-like languages. For example:
>
> def inc(x):
> x += 1
>
> n = 1
> inc(n)
> assert n == 2
>
> Why doesn't that work? This is completely mysterious to anyone
> expecting
> C-like variables.

Hmm... I'm not following you. That wouldn't work in C, either. 'x'
in 'inc' is a local variable; its value is just a copy of whatever
value you pass in. You can increment it all you want, and it won't
affect the original variable (if indeed it was a variable that the
value came from; it could be a literal or an expression or who knows
what else).

> At this point people will often start confusing the issue by claiming
> that "all Python variables are pointers", which is an *implementation
> detail* in CPython but not in other implementations, like PyPy or
> Jython.

I'm not claiming that -- and I'm trying to clarify, rather than
confuse the issue. (Of course if it turns out that my understanding
of Python is incorrect, then I'm hoping to uncover and correct that,
too.)

> Or people will imagine that Python makes a copy of the variable when
> you
> call a function. That's not true, and in fact Python explicitly
> promises
> never to copy a value unless you explicitly tell it to

Now that IS mysterious. Doesn't calling a function add a frame to a
stack? And doesn't that necessitate copying in values for the
variables in that stack frame (such as 'x' above)? Of course we're
now delving into internal implementation details... but it sure
behaves as though this is exactly what it's doing (and is the same
thing every other language does, AFAIK).

> but it seems to explain the above, at least until the programmer
> starts *assuming* call-
> by-value behaviour and discovers this:
>
> def inc(alist):
> alist += [1] # or alist.append(1) if you prefer
> return alist

It's still call-by-value behavior. The value in this case is a list
reference. Using .append, or the += operator, modifies the list
referred to by that list reference. Compare that to:

def inc(alist):
alist = alist + [1]
return alist

where you are not modifying the list passed in, but instead creating a
new list, and storing a reference to that in local variable 'alist'.

The semantics here appear to be exactly the same as Java or REALbasic
or any other modern language: variables are variables, and parameters
are local variables with called by value, and it just so happens that
some values may be references to data on the heap.

> Are functions call by value or call by reference???
>
> (Answer: neither. They are call by name.)

I have no idea what that means. They're call by value as far as I can
tell. (Even if the value may happen to be a reference.)

Side question, for my own education: *does* Python have a "ByRef"
parameter mode?

> I myself often talk about variables as shorthand. But it's a bad
> habit,
> because it is misleading to anyone who thinks they know how variables
> behave, so when I catch myself doing it I fix it and talk about name
> bindings.

Perhaps you have a funny idea of what people think about how variables
behave. I suspect that making up new terminology for perfectly
ordinary things (like Python variables) makes them more mysterious,
not less.

> Of course, you're entitled to define "variable" any way you like, and
> then insist that Python variables don't behave like variables in other
> languages. Personally, I don't think that's helpful to anyone.

No, but if we define them in the standard way, and point out that
Python variables behave exactly like variables in other languages,
then that IS helpful.

>> Well, they are variables. I'm not quite grasping the difficulty
>> here...
>> unless perhaps you were (at first) thinking of the variables as
>> holding
>> the object values, rather than the object references.
>
> But that surely is what almost everyone will think, almost all the
> time.
> Consider:
>
> x = 5
> y = x + 3
>
> I'm pretty sure that nearly everyone will read it as "assign 5 to x,
> then
> add 3 to x and assign the result to y" instead of:
>
> "assign a reference to the object 5 to x, then dereference x to get
> the
> object 5, add it to the object 3 giving the object 8, and assign a
> reference to that result to y".

True. I have no reason to believe that, in the case of a number, the
value isn't the number itself. (Except for occasional claims that
"everything in Python is an object," but if that's literally true,
what are the observable implications?)

> Of course that's what's really happening under the hood, and you can't
> *properly* understand how Python behaves without understanding that.
> But
> I'm pretty sure few people think that way naturally, especially noobs.

In this sense I'm still a noob -- until a couple weeks ago, I hadn't
touched Python in over a decade. So I sure appreciate this
refresher. If numbers really are wrapped in objects, that's
surprising to me, and I'd like to learn about any cases where you can
actually observe this. (It's not apparent from the behavior of the +=
operator, for example... if they are objects, I would guess they are
immutable.)

But it's not at all surprising with lists and dicts and objects --
every modern language passes around references to those, rather than
the data themselves, because the data could be huge and is often
changing size all the time. Storing the values in a variable would
just be silly.

> References are essentially like pointers, and learning pointers is
> notoriously difficult for people.

Hmm... I bet you're over 30. :) So am I, for that matter, so I can
remember when people had to learn "pointers" and found it difficult.
But nowadays, the yoots are raised on Java, or are self-taught on
something like REALbasic or .NET (or Python). There aren't any
pointers, but only references, and the semantics are the same in all
those languages. Pointer difficulty is something that harkens back to
C/C++, and they're just not teaching that anymore, except to the EE
majors.

So, if the semantics are all the same, I think it's helpful to use the
standard terminology.

> Python does a magnificent job of making
> references easy, but it does so by almost always hiding the fact
> that it
> uses references under the hood. That's why talk about variables is so
> seductive and dangerous: Python's behaviour is *usually* identical
> to the
> behaviour most newbies expect from a language with "variables".

You could be right, when it comes to numeric values -- if these are
immutable objects, then I can safely get by thinking of them as pure
values rather than references (which is what they are in RB, for
example). Strings are another such case: as immutable, you can safely
treat them as values, but it's comforting to know that you're not
incurring the penalty of copying a huge data buffer every time you
pass one to a function or assign it to another variable.

But with mutable objects, it is ordinary and expected that what you
have is a reference to the object, and you can tell this quite simply
by mutating the object in any way. Every modern language I know works
the same way, and I'd wager that the ones I don't know (e.g. Ruby)
also work that way. Python's a beautiful language, but I'm afraid
it's nothing special in this particular regard.

Best,
- Joe

Message has been deleted

Joe Strout

unread,
Oct 17, 2008, 11:56:17 AM10/17/08
to Python List
On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:

> On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <j...@strout.net>
> declaimed the following in comp.lang.python:


>
>> Now that IS mysterious. Doesn't calling a function add a frame to a
>> stack? And doesn't that necessitate copying in values for the
>> variables in that stack frame (such as 'x' above)? Of course we're
>

> No -- it copies the /reference/ to the object containing the value.

The reference to the object IS the value of an object reference
variable. So good, parameters are passed ByVal in Python as they
appear to be, and as is the default in every other modern language.

> Just as assignment transfers the reference to the RHS object to the
> name
> shown on the LHS.

Assignment copies the RHS value to the LHS variable. In the case of
an object reference, the value copied is, er, an object reference.

>> The semantics here appear to be exactly the same as Java or REALbasic
>> or any other modern language: variables are variables, and parameters
>> are local variables with called by value, and it just so happens that
>> some values may be references to data on the heap.
>>

> ALL "values" are references to data in Python -- but some of those
> values are immutable objects so any operation performed on them
> creates
> new objects, and the assignment is of a new reference.

OK, that part is a little different from most languages -- not in the
way objects are treated, but in the fact that even simple values like
integers are wrapped in objects. But since those are immutable
objects, this is mostly an internal implementation detail.

For object references (including the mutable ones that may treat
people up), Python's behavior is no different from any other language.

>>> (Answer: neither. They are call by name.)
>>
>> I have no idea what that means. They're call by value as far as I
>> can
>> tell. (Even if the value may happen to be a reference.)
>

> Technically, as I recall the definition of "call by name", they
> aren't that either. ...
> Call by name, then, acted as a macro expansion wherever the argument
> was referenced in the called function.

Thanks for that explanation. Clearly that's not what's going on in
Python.

>> Side question, for my own education: *does* Python have a "ByRef"
>> parameter mode?
>>

> As far as I'm concerned -- everything is "by ref" in Python...

No, a "by ref" parameter would mean that this:

def foo(ByRef x):
x = x + [42]

a = [1,2,3]
foo(a)

...would result in a = [1,2,3,42]. You would only be able to pass a
simple variable (not an expression or literal) to foo, and the 'x'
inside foo would not be a local variable, but an alias of whatever
variable was passed in. Thus any assignments to it would affect the
original variable that was passed in.

But if Python has any such feature, I'm not aware of it. Certainly
the default behavior is to pass everything (even object references) by
value. Assignments made to them don't affect anything else.

> Mutation of an object is never a bare LHS... It is either a method
> call of the name
>
> alist.append()
>
> or a drill-down going inside the object
>
> alist[2] = something
> anobject.attribute = something
> adict["key"] = something

Or, use of one of the compound operators like +=. That's the only
real "gotcha" in Python to somebody coming from another language; you
might naively expect that x += y is the same as x = x+y, but in Python
this is not generally the case; instead += is a mutation operator,
like the examples you show above.

> But every language I've used (many: FORTRAN, C, C++, BASIC, VB,
> Assembly, COBOL, Ada...) treats "variable" as "name of fixed
> location in
> memory" and assignment to the variable means "replace the contents of
> the location of memory associated with this name with the contents of
> memory to which that name (may be anonymous in the case of an
> expression) is associated by copying the contents from there to here"

That's what Python does too. It just so happens that the fixed
location in memory contains an object reference. No difference here
between Python's object references VB.NET's object references, C++
pointers, Java object references, etc. etc.

> Python, OTOH, ALWAYS handles assignment as "change the memory
> association of this name to be the same as that name".

What does that mean, exactly? It means: "replace the contents (i.e.
object reference) of the memory location associated with this name
with the contents (i.e. object reference) of the memory to which that
name is associated by copying the contents from there to here."

It's the exact same thing. (And exactly the same as in any other
language.)

>> No, but if we define them in the standard way, and point out that
>> Python variables behave exactly like variables in other languages,
>> then that IS helpful.
>>

> But they don't...

They really, really do.

>> But it's not at all surprising with lists and dicts and objects --
>> every modern language passes around references to those, rather than
>> the data themselves, because the data could be huge and is often
>> changing size all the time. Storing the values in a variable would
>> just be silly.
>>

> In most all of those languages, one has to explicitly differentiate
> the the difference between a copy and a reference.

Only if you're thinking of languages from 20 years ago or more. Even
in C++, while there is a different bit of kludgy syntax for object
"references" (because they're mere pointers), it's the standard to use
such pointers everywhere that objects are handled. Java cleaned up
that kludginess by replacing the pointers with proper references, as
did VB.NET, REALbasic, probably Ruby, and of course Python.

> And even that is not
> assured... As I recall, nothing in the Ada language reference forbids
> implementing an "in out" procedure parameter from being implemented
> via
> copy-in/copy-out semantics rather than via reference.

Hah, well probably so. Ada even predates me, and I'm not all that
young anymore!

>> Hmm... I bet you're over 30. :) So am I, for that matter, so I can
>> remember when people had to learn "pointers" and found it difficult.
>

> Bah... The roots of I/O in Pascal required pointer dereferencing.

Hey, I remember Pascal... that was the language used on the Apple
IIGS, back when I was in junior high. I also remember spending $800
for a 40MB hard drive for it. Ah, those were the days!

>> So, if the semantics are all the same, I think it's helpful to use
>> the
>> standard terminology.
>>

> But, it seems, you are the only one arguing that "the semantics are
> all the same"... Doesn't that suggest that they aren't the same?

No, it suggests to me that there's a lot of confusion in the Python
community. :) It appears as though people either (a) really want to
think that Python's object handling is special and unique for
emotional reasons, or (b) are comparing it to really ancient languages
that didn't have any notion of objects and object references. This
has led to making up new terminology and spreading confusion. I'm
coming back to Python from almost a decade of working with other
modern languages (including implementing the compiler for one of
them), and I don't see any difference at all between Python's object
handling and those.

Best,
- Joe


Aaron "Castironpi" Brady

unread,
Oct 17, 2008, 3:03:50 PM10/17/08
to
On Oct 17, 10:56 am, Joe Strout <j...@strout.net> wrote:
> On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
snip

> >    But, it seems, you are the only one arguing that "the semantics are
> > all the same"... Doesn't that suggest that they aren't the same?
>
> No, it suggests to me that there's a lot of confusion in the Python  
> community.  :)  It appears as though people either (a) really want to  
> think that Python's object handling is special and unique for  
> emotional reasons, or (b) are comparing it to really ancient languages  
> that didn't have any notion of objects and object references.  This  
> has led to making up new terminology and spreading confusion.  I'm  
> coming back to Python from almost a decade of working with other  
> modern languages (including implementing the compiler for one of  
> them), and I don't see any difference at all between Python's object  
> handling and those.
>
> Best,
> - Joe

I'm not fluent in Java so you'll have to be the judge.

In Python:

b= 0
f( b )

No matter what, b == 0. C doesn't guarantee this. Does Java?

Further:

b= {}
c= b
f( b )

No matter what, 'c is b' is true. C doesn't have an 'is' operator.
Does Java?

Lastly, the word 'same' is ambiguous or poorly defined. It can mean
either 'identical' or 'equal'.

Joe Strout

unread,
Oct 17, 2008, 3:32:18 PM10/17/08
to Python List
On Oct 17, 2008, at 1:03 PM, Aaron Castironpi Brady wrote:

> I'm not fluent in Java so you'll have to be the judge.
>
> In Python:
>
> b= 0
> f( b )
>
> No matter what, b == 0. C doesn't guarantee this.

It does, unless f's parameter has been declared a reference
parameter. (In C++, you'd do this with '&'; I didn't think it was
possible in C, but it's been a long time since I've used C so maybe it
is possible nowadays.)

> Does Java?

Same in Java, and in RB, and in .NET too. If f's parameter is a by-
value parameter, then it acts exactly like Python. (Those languages
also allow a by-reference parameter declaration, which I think Python
doesn't allow, but by-value is the default.)

> Further:
>
> b= {}
> c= b
> f( b )
>
> No matter what, 'c is b' is true.

Right, again, this just demonstrates that Python passes values by
reference.

> C doesn't have an 'is' operator.

Well, that's literally true, but only because it doesn't have a deep
equality operator like modern languages. In C, b and c would be
pointers, and 'c == b' would be the equivalent of Python's 'c is
b' (and would be true after the call to f, again assuming you didn't
go out of your way to declare f with a by-reference parameter).

> Does Java?

Yes. The behavior's the same. Same also in every other OOP language,
as far as I know.

I think all we've established here is that Python always passes
parameters by value, and in most other languages, passing by value is
the default (but there's an option to pass by reference if you want).

Python lacks the ByRef-parameter feature, so when that's what you need
to do, you'd have to wrap your value in some mutable type (like a
list) and pass that instead. A little awkward, but no big deal, as
there are darn few valid reasons to ever pass something by reference
anyway, especially in a language with tuple packing and unpacking.

Best,
- Joe


Steve Holden

unread,
Oct 17, 2008, 4:36:24 PM10/17/08
to pytho...@python.org
Joe Strout wrote:
> On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
[much blether]

>>> Side question, for my own education: *does* Python have a "ByRef"
>>> parameter mode?
>>>
>> As far as I'm concerned -- everything is "by ref" in Python...
>
> No, a "by ref" parameter would mean that this:
>
> def foo(ByRef x):
> x = x + [42]
>
> a = [1,2,3]
> foo(a)
>
> ...would result in a = [1,2,3,42]. You would only be able to pass a
> simple variable (not an expression or literal) to foo, and the 'x'
> inside foo would not be a local variable, but an alias of whatever
> variable was passed in. Thus any assignments to it would affect the
> original variable that was passed in.
>
In [8]: def foo(x):
...: x += [42]
...:

In [9]: a = [1, 2, 3]

In [10]: foo(a)

In [11]: a
Out[11]: [1, 2, 3, 42]

In [12]: def ffoo(x):
....: x.append(43)
....:

In [13]: ffoo(a)

In [14]: a
Out[14]: [1, 2, 3, 42, 43]

In [15]: def fffoo(a):
....: a = a + [42]
....:

In [16]: fffoo(a)

In [17]: a
Out[17]: [1, 2, 3, 42, 43]

So, is it call by reference or not? Does that depend on the
implementation of specific operators?

You problem seems to be that you ar still stuck with the notion of a
name as a reference to a specific area of memory. Which it's not,
excepting only if you want to consider the area of memory that holds a
reference to some value.

In the case of lists,

a = a + [something]

rebinds a, while

a += [something]

doesn't. So where does that leave you?

> But if Python has any such feature, I'm not aware of it. Certainly the
> default behavior is to pass everything (even object references) by
> value. Assignments made to them don't affect anything else.
>
>> Mutation of an object is never a bare LHS... It is either a method
>> call of the name
>>
>> alist.append()
>>
>> or a drill-down going inside the object
>>
>> alist[2] = something
>> anobject.attribute = something
>> adict["key"] = something
>
> Or, use of one of the compound operators like +=. That's the only real
> "gotcha" in Python to somebody coming from another language; you might
> naively expect that x += y is the same as x = x+y, but in Python this is
> not generally the case; instead += is a mutation operator, like the
> examples you show above.
>

Be careful though:

In [18]: a = 42

In [19]: id(a)
Out[19]: 14237932

In [20]: a += 1

In [21]: id(a)
Out[21]: 14237920

In [22]: a = []

In [23]: id(a)
Out[23]: 2140206636

In [24]: a += [42]

In [25]: id(a)
Out[25]: 2140206636

In other words, the behavior of augmented operations depends on whether
the reference is to a mutable or an immutable value.

>> But every language I've used (many: FORTRAN, C, C++, BASIC, VB,
>> Assembly, COBOL, Ada...) treats "variable" as "name of fixed location in
>> memory" and assignment to the variable means "replace the contents of
>> the location of memory associated with this name with the contents of
>> memory to which that name (may be anonymous in the case of an
>> expression) is associated by copying the contents from there to here"
>
> That's what Python does too. It just so happens that the fixed location
> in memory contains an object reference. No difference here between
> Python's object references VB.NET's object references, C++ pointers,
> Java object references, etc. etc.
>
>> Python, OTOH, ALWAYS handles assignment as "change the memory
>> association of this name to be the same as that name".
>

It might be simpler to say "Change this name to be a reference to that
value", or "Change this name to be a reference to the [result of
evaluating the] expression on the RHS".

Or indeed, "Change the content of that container element to be a
reference to the [result of evaluating the] expression on the RHS"

> What does that mean, exactly? It means: "replace the contents (i.e.
> object reference) of the memory location associated with this name with
> the contents (i.e. object reference) of the memory to which that name
> is associated by copying the contents from there to here."
>
> It's the exact same thing. (And exactly the same as in any other
> language.)
>

If you mean it's a reference assigment, of course it is. That's what he
was trying to say (I believe). But in C, for example,

int i;
i = 42;

actually stores the value 42 in the location associated with the name c.
Quite different from

int *i;
i = &42;

[Is that even valid C?] That's almost what Python does with

i = 42

>>> No, but if we define them in the standard way, and point out that
>>> Python variables behave exactly like variables in other languages,
>>> then that IS helpful.
>>>

>> But they don't...
>
> They really, really do.
>

>>> But it's not at all surprising with lists and dicts and objects --
>>> every modern language passes around references to those, rather than
>>> the data themselves, because the data could be huge and is often
>>> changing size all the time. Storing the values in a variable would
>>> just be silly.
>>>

>> In most all of those languages, one has to explicitly differentiate
>> the the difference between a copy and a reference.
>
> Only if you're thinking of languages from 20 years ago or more. Even in
> C++, while there is a different bit of kludgy syntax for object
> "references" (because they're mere pointers), it's the standard to use
> such pointers everywhere that objects are handled. Java cleaned up that
> kludginess by replacing the pointers with proper references, as did
> VB.NET, REALbasic, probably Ruby, and of course Python.
>
>> And even that is not
>> assured... As I recall, nothing in the Ada language reference forbids
>> implementing an "in out" procedure parameter from being implemented via
>> copy-in/copy-out semantics rather than via reference.
>
> Hah, well probably so. Ada even predates me, and I'm not all that young
> anymore!
>

>>> Hmm... I bet you're over 30. :) So am I, for that matter, so I can
>>> remember when people had to learn "pointers" and found it difficult.
>>

>> Bah... The roots of I/O in Pascal required pointer dereferencing.
>
> Hey, I remember Pascal... that was the language used on the Apple IIGS,
> back when I was in junior high. I also remember spending $800 for a
> 40MB hard drive for it. Ah, those were the days!
>

40 Mb! You were lucky! Etc., etc., [drools into beard.]

>>> So, if the semantics are all the same, I think it's helpful to use the
>>> standard terminology.
>>>

>> But, it seems, you are the only one arguing that "the semantics are
>> all the same"... Doesn't that suggest that they aren't the same?
>
> No, it suggests to me that there's a lot of confusion in the Python
> community. :) It appears as though people either (a) really want to
> think that Python's object handling is special and unique for emotional
> reasons, or (b) are comparing it to really ancient languages that didn't
> have any notion of objects and object references. This has led to
> making up new terminology and spreading confusion. I'm coming back to
> Python from almost a decade of working with other modern languages
> (including implementing the compiler for one of them), and I don't see
> any difference at all between Python's object handling and those.
>

Python's assignment semantics (as opposed to its "object handling, a
term for which I have no referent) are not the same as those of, say C.
I believe they are pretty much the same ass those of Icon, another
non-standard interpreted language.

There are close similarities between Python's names and C reference
variables, but the semantics are not exactly parallel.

People here don't describe Python as different just because they *want*
it to be different. Python acknowledges intellectual debts to many
languages, none of which is exactly like it.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Joe Strout

unread,
Oct 17, 2008, 5:03:00 PM10/17/08
to Steve Holden, pytho...@python.org

On Oct 17, 2008, at 2:36 PM, Steve Holden wrote:

>> No, a "by ref" parameter would mean that this:
>>
>> def foo(ByRef x):
>> x = x + [42]
>>
>> a = [1,2,3]
>> foo(a)
>>
>> ...would result in a = [1,2,3,42].
>>

> In [8]: def foo(x):
> ...: x += [42]
> ...:
>
> In [9]: a = [1, 2, 3]
>
> In [10]: foo(a)
>
> In [11]: a
> Out[11]: [1, 2, 3, 42]

This demonstrates that lists are mutable, and that += is a mutating
operator (and NOT an assignment).

> In [12]: def ffoo(x):
> ....: x.append(43)
> ....:
>
> In [13]: ffoo(a)
>
> In [14]: a
> Out[14]: [1, 2, 3, 42, 43]

Ditto (but for the .append method).

> In [15]: def fffoo(a):
> ....: a = a + [42]
> ....:
>
> In [16]: fffoo(a)
>
> In [17]: a
> Out[17]: [1, 2, 3, 42, 43]

And here, you're doing an assignment -- this is the only test of the
three that tests whether the parameter is passed by reference or by
value. The result: it's by value.

> So, is it call by reference or not?

Not.

> Does that depend on the implementation of specific operators?

No.

> You problem seems to be that you ar still stuck with the notion of a
> name as a reference to a specific area of memory. Which it's not,
> excepting only if you want to consider the area of memory that holds a
> reference to some value.

Which is exactly what it is, so that's what you should consider.

And my real point is that this is exactly the same as in every other
modern language. Nothing unusual here at all (except that some of us
here seem to want to make up new terminology for standard behavior,
perhaps in order to make Python seem more exotic).

> In the case of lists,
>
> a = a + [something]
>
> rebinds a

In standard terminology, it assigns a new value to a.

> while
>
> a += [something]
>
> doesn't.

Correct.

> So where does that leave you?

In exactly the same happy boat as Java, RB, .NET, etc. (even C++ if
you consider an object pointer to be the equivalent of an object
reference).

>> Or, use of one of the compound operators like +=. That's the only
>> real
>> "gotcha" in Python to somebody coming from another language; you
>> might
>> naively expect that x += y is the same as x = x+y, but in Python
>> this is
>> not generally the case; instead += is a mutation operator, like the
>> examples you show above.
>>
> Be careful though:
>
> In [18]: a = 42
>
> In [19]: id(a)
> Out[19]: 14237932
>
> In [20]: a += 1
>
> In [21]: id(a)
> Out[21]: 14237920

Good point -- obviously += can't mutate an immutable type. In those
cases it IS equivalent to an assignment. I can certainly see why
these operators can trip people up at first.

>> It's the exact same thing. (And exactly the same as in any other
>> language.)
>>
> If you mean it's a reference assigment, of course it is. That's what
> he
> was trying to say (I believe). But in C, for example,
>
> int i;
> i = 42;
>
> actually stores the value 42 in the location associated with the
> name c.

Yes, but let's get away from numbers, since those are a bit of a
special case, and not where the argument is revolving. (Since
Python's number-wrappers are immutable, they are behaviorally
equivalent to raw values, and so it really doesn't matter whether you
know that they're actually objects or not).

The discussion at hand is how best to explain and understand mutable
types. I don't remember C too well, but in C++ that'd be something
like:

Foo *x;
x = FooFactory();

This stores the address of the object FooFactory builds into x. It's
equivalent to what Python does with

x = FooFactory()

...except, of course, that Python's syntax is cleaner, and you don't
have all the rope that C/C++ gives you with which to shoot yourself in
the foot.

>> Hey, I remember Pascal... that was the language used on the Apple
>> IIGS,
>> back when I was in junior high. I also remember spending $800 for a
>> 40MB hard drive for it. Ah, those were the days!
>>
> 40 Mb! You were lucky! Etc., etc., [drools into beard.]

:)

> Python's assignment semantics (as opposed to its "object handling, a
> term for which I have no referent) are not the same as those of, say
> C.

They are, though. The only difference you've pointed out is that
*numbers* are different in Python vs. C, and that's an internal
implementation detail I was blissfully unaware of until this
discussion. (I'm grateful to know it, but it really doesn't matter in
day-to-day coding.)

> I believe they are pretty much the same ass those of Icon, another
> non-standard interpreted language.

They're also the same as RB, Java, .NET... I'm hoping somebody who
knows some other modern OOP language (e.g. Ruby) will weigh in,
because I bet it's the same as those too.

Comparing it to C isn't really fair, because C isn't even an OOP
language. C++ would at least be in the same ballpark.

> There are close similarities between Python's names and C reference
> variables, but the semantics are not exactly parallel.

I agree; reference variables are an odd beast, most commonly used (and
most similar to) a ByRef parameter in modern languages. And it seems
that Python simply doesn't have that.

> People here don't describe Python as different just because they
> *want*
> it to be different. Python acknowledges intellectual debts to many
> languages, none of which is exactly like it.

Sure, nothing's exactly like it in all ways. But its object handling
[*] is, in fact, exactly like every other modern OOP language.

Best,
- Joe

[*] Object handling: the ways in which objects are created, stored,
referenced, assigned, and passed into and out of method calls.


Grant Edwards

unread,
Oct 17, 2008, 5:19:39 PM10/17/08
to
On 2008-10-17, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 2:36 PM, Steve Holden wrote:

>> You problem seems to be that you ar still stuck with the
>> notion of a name as a reference to a specific area of memory.
>> Which it's not, excepting only if you want to consider the
>> area of memory that holds a reference to some value.
>
> Which is exactly what it is, so that's what you should
> consider.
>
> And my real point is that this is exactly the same as in every
> other modern language.

No, it isn't. In many other languages (C, Pascal, etc.), a
"variable" is commonly thought of as a fixed location in memory
into which one can put values. Those values may be references
to objects. In Python, that's not how it works. There is no
"location in memory" that corresponds to a variable with a
particular name the way there is in C or Pascal or Fortran or
many other languages.

All that exists in Python is a name->object mapping.

> Nothing unusual here at all (except that some of us here seem
> to want to make up new terminology for standard behavior,
> perhaps in order to make Python seem more exotic).

That's because it is fundamentally different from what happens
in languages like C.

>> In the case of lists,
>>
>> a = a + [something]
>>
>> rebinds a
>
> In standard terminology, it assigns a new value to a.

The problem is that listeners from a C or FORTRAN background
will infer that there is a fixed region of memory named "a" and
"assigning a value to a" means writing that new value into the
region of memory named "a". Saying "rebinding" is a way of
helping people with backgrounds in non-dynamic languages that
there is no chunk of memory named "a" and that assigments
aren't doing the same thing they do in C or FORTRAN.

--
Grant Edwards grante Yow! My mind is a potato
at field ...
visi.com

Joe Strout

unread,
Oct 17, 2008, 5:39:33 PM10/17/08
to Python List
On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:

>> And my real point is that this is exactly the same as in every
>> other modern language.
>
> No, it isn't. In many other languages (C, Pascal, etc.), a
> "variable" is commonly thought of as a fixed location in memory
> into which one can put values. Those values may be references
> to objects.

Right, though not in languages like C and Pascal that don't HAVE the
notion of objects. We really ought to stop bringing up those
dinosaurs and instead compare Python to any modern OOP language.

> In Python, that's not how it works. There is no
> "location in memory" that corresponds to a variable with a
> particular name the way there is in C or Pascal or Fortran or
> many other languages.

No? Is there any way to prove that, without delving into the Python
source itself?

If not, then I think you're talking about an internal implementation
detail.

> All that exists in Python is a name->object mapping.

And what does that name->object mapping consist of? At some level,
there has to be a memory location that stores the reference to the
object, right?

>> Nothing unusual here at all (except that some of us here seem
>> to want to make up new terminology for standard behavior,
>> perhaps in order to make Python seem more exotic).
>
> That's because it is fundamentally different from what happens
> in languages like C.

What happens in a modern OOP language is just as fundamentally
different (which is to say, not really very much) from what happens in
C or FORTRAN or COBOL, too.

But if there's any demonstrable difference between Python and any
other modern OOP language, I'd love to hear about it.

>>> a = a + [something]
>>>
>>> rebinds a
>>
>> In standard terminology, it assigns a new value to a.
>
> The problem is that listeners from a C or FORTRAN background
> will infer that there is a fixed region of memory named "a" and
> "assigning a value to a" means writing that new value into the
> region of memory named "a".

And they'd be correct. The value being written, in this case, as a
reference to some data that lives somewhere on the heap. Point that
out, and now their understanding is correct.

But if you instead say something like "all parameters are passed by
reference in Python," then the user gets the wrong idea. That
statement has a specific meaning which is, quite demonstrably, not true.

If you make up new terms like "rebinds," well, I guess at least that
avoids giving the listener the wrong idea. Instead it gives them no
idea at all, which may be better, but not as good as giving them the
right idea. It still leaves them to investigate what actually
happens, and ultimately they will find that the parameters are always
passed by value in Python. May as well save them the trouble and
point that out up front.

And how many recovering FORTRAN or C programmers do we get around
here, anyway? Java is what they've been teaching in school for the
last several years, and it was C++ for a good decade before that. The
semantics of Python (insofar as objects, assignments, and parameters
are concerned) are exactly the same as Java, and Java is just a
cleaned-up and streamlined C++. Even old-timers (like me) who learned
FORTRAN and COBOL way back in the day have long since moved on.

Best,
- Joe

Aaron "Castironpi" Brady

unread,
Oct 17, 2008, 6:50:36 PM10/17/08
to
On Oct 17, 4:03 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 2:36 PM, Steve Holden wrote:
snip

> And here, you're doing an assignment -- this is the only test of the  
> three that tests whether the parameter is passed by reference or by  
> value.  The result: it's by value.
>
> > So, is it call by reference or not?
>
> Not.

But it's not by value, q.e.d.
snip

> ...except, of course, that Python's syntax is cleaner...

Excepting that thou then proceedst to 3.

snip

Message has been deleted

George Sakkis

unread,
Oct 17, 2008, 7:34:47 PM10/17/08
to
On Oct 17, 5:19 pm, Grant Edwards <gra...@visi.com> wrote:

> On 2008-10-17, Joe Strout <j...@strout.net> wrote:
>
> > And my real point is that this is exactly the same as in every
> > other modern language.

^^^^^^^^^

> No, it isn't. In many other languages (C, Pascal, etc.), a

^^^^^^^^^^^^^^^^^
Methinks the only real disagreement in this thread is what's a
"modern" language; Joe has made clear that he's not comparing Python
to C, Pascal or Fortran.

George

MRAB

unread,
Oct 17, 2008, 8:02:21 PM10/17/08
to
On Oct 17, 10:03 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 2:36 PM, Steve Holden wrote:
>
[big snip]

> > I believe they are pretty much the same ass those of Icon, another
> > non-standard interpreted language.
>
> They're also the same as RB, Java, .NET... I'm hoping somebody who  
> knows some other modern OOP language (e.g. Ruby) will weigh in,  
> because I bet it's the same as those too.
>
[snip]
The difference is that Python uses dictionaries. When you write:

x = 42

what actually happens is something like:

globals()["x"] = 42

or:

locals()["x"] = 42

The name of the "variable" is a key in a dictionary with the value (a
reference to an object) that was "assigned" being the associated
value. When you "del" a "variable", eg del x, you're removing the
entry from the dictionary.

In Java the variables are like members in a struct (or fields in a
record in Pascal parlance) with the value that was assigned being its
content. (In Java there's also the detail that primitive types like
int are stored directly and not as references for reasons of speed.)

Steven D'Aprano

unread,
Oct 19, 2008, 1:52:33 AM10/19/08
to
On Fri, 17 Oct 2008 15:39:33 -0600, Joe Strout wrote:

> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
>
>>> And my real point is that this is exactly the same as in every other
>>> modern language.
>>
>> No, it isn't. In many other languages (C, Pascal, etc.), a "variable"
>> is commonly thought of as a fixed location in memory into which one can
>> put values. Those values may be references to objects.
>
> Right, though not in languages like C and Pascal that don't HAVE the
> notion of objects. We really ought to stop bringing up those dinosaurs
> and instead compare Python to any modern OOP language.

You really should stop assuming that languages still in use are
"dinosaurs". There are many, many people whose understanding of such
terms as "call by value" or "variable" are based on C or Pascal or even
Fortran.

Besides, while the Pascal language itself doesn't have objects, plenty of
Pascal implementations do.


>> In Python, that's not how it works. There is no
>> "location in memory" that corresponds to a variable with a particular
>> name the way there is in C or Pascal or Fortran or many other
>> languages.
>
> No? Is there any way to prove that, without delving into the Python
> source itself?

>>> x = 1
>>> id(x) # a unique identifier, in CPython equal to its address
135536432
>>> x = 2
>>> id(x)
135536420

Notice that the address of x changes. Actually, that's a lie. The name
'x' doesn't have an address, except in the sense that the string 'x' must
occur somewhere in memory. But that's an unimportant implementation
detail. In reality, what we see is:

the object 1 is bound to the name 'x';
we ask for the id() of the object bound to 'x' (1), which is 135536432;
the object 2 is bound to the name 'x';
we ask for the id() of the object bound to 'x' (2), which is 135536420.

That's what is happening at the Python level of code. Anything else is
just implementation details.

> If not, then I think you're talking about an internal implementation
> detail.

Namespaces aren't an internal implementation detail, they are fundamental
to how Python works.


>> All that exists in Python is a name->object mapping.
>
> And what does that name->object mapping consist of? At some level,
> there has to be a memory location that stores the reference to the
> object, right?

Who cares? That's the *wrong* level. At *some* level, everything is just
flipping electrons from one state to another, but I think even you would
object if I claimed that:

"All computer languages are call-by-flipping-electrons, with no
exceptions."


Somebody could implement a Python interpreter using literal post-it notes
for names and literal boxes for objects. The fact that our CPUs are
optimized for flipping bits instead of (say) water flowing through tubes,
or clockwork, or punching holes in paper tape, is irrelevant. When
discussing what Python code does, the right level is to discuss the
Python virtual machine, not the implementation of that VM.

If you want to discuss the deeper levels, it's perfectly acceptable to
say that the CPython implementation uses memory locations holding
pointers. But that's not *Python*, that's hidden detail that the Python
programmer can't reach.

>>> Nothing unusual here at all (except that some of us here seem to want
>>> to make up new terminology for standard behavior, perhaps in order to
>>> make Python seem more exotic).
>>
>> That's because it is fundamentally different from what happens in
>> languages like C.
>
> What happens in a modern OOP language is just as fundamentally different
> (which is to say, not really very much) from what happens in C or
> FORTRAN or COBOL, too.

Which is why modern OOP languages like Python shouldn't use the same
terminology invented to describe what Fortran and Pascal do.


> If you make up new terms like "rebinds,"

This is not something that is just "made up", it is an actual description
of what the Python VM does.


> well, I guess at least that
> avoids giving the listener the wrong idea.

As opposed to call-by-value, call-by-reference, and "call-by-value-where-
the-value-is-the-reference", all of which do give the listener the wrong
idea.


> Instead it gives them no
> idea at all, which may be better, but not as good as giving them the
> right idea.

But it is the right idea. They just don't know what it means, because
they've been listening to people like you who insist on using Pascal
terminology with a definition unrecognizable to Pascal programmers. To an
ex-Pascal programmer like myself, when you talk about "call by value
where the value is a reference", it sounds to me as if you are insisting
that cars are ACTUALLY horse and buggies, where the horse is the engine,
why are we inventing new terms like 'automobile', that just confuses
people.

> It still leaves them to investigate what actually happens,
> and ultimately they will find that the parameters are always passed by
> value in Python.

But they aren't. When you call a function, the arguments are not copied
before being passed to the function.

> May as well save them the trouble and point that out
> up front.

Well, sure, if you want to be misleading and confusing.

> And how many recovering FORTRAN or C programmers do we get around here,
> anyway?

Enough.

It's not just people who have programmed Pascal, but those whose
understanding of CBV and CBR have been shaped by ancient half-remembered
Pascal lessons.


> Java is what they've been teaching in school for the last
> several years, and it was C++ for a good decade before that.

Have they really? Which school is that?

My company has hired a part-time young gun programmer. He's still at Uni,
doing Comp Sci, and has *far* wider IT experience than the average
programmer his age. His skills? PHP, Perl, C, oh and he's just starting
to learn C++ this semester.

There are plenty of programmers who have never been to university or
collage, and even some who have never learnt programming in school at
all. Believe it or not, it's not compulsory.

--
Steven

Message has been deleted

Steven D'Aprano

unread,
Oct 19, 2008, 5:07:25 AM10/19/08
to
On Fri, 17 Oct 2008 16:36:24 -0400, Steve Holden wrote:

> People here don't describe Python as different just because they *want*
> it to be different. Python acknowledges intellectual debts to many
> languages, none of which is exactly like it.

I understand that Python's object and calling semantics are exactly the
same as Emerald (and likely other languages as well), and that both
Emerald and Python are explicitly based on those of CLU, as described by
by Barbara Liskov in 1979:

"In particular it is not call by value because mutations
of arguments performed by the called routine will be
visible to the caller. And it is not call by reference
because access is not given to the variables of the
caller, but merely to certain objects."

http://www.lcs.mit.edu/publications/pubs/pdf/MIT-LCS-TR-225.pdf

quoted by Fredrik Lundh here:
http://mail.python.org/pipermail/python-list/2003-May/204379.html


"Call by object/sharing" isn't some new-fangled affectation invented by
comp.lang.python dweebs to make Python seem edgy and different. It's a
term that has been in use in highly respected Comp Sci circles for over
thirty years. In case anybody doesn't recognise the name:

http://en.wikipedia.org/wiki/Barbara_Liskov


--
Steven

Steven D'Aprano

unread,
Oct 19, 2008, 7:42:11 AM10/19/08
to
On Fri, 17 Oct 2008 09:56:17 -0600, Joe Strout wrote:

> On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
>
>> On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <j...@strout.net>
>> declaimed the following in comp.lang.python:
>>
>>> Now that IS mysterious. Doesn't calling a function add a frame to a
>>> stack? And doesn't that necessitate copying in values for the
>>> variables in that stack frame (such as 'x' above)? Of course we're
>>
>> No -- it copies the /reference/ to the object containing the value.
>
> The reference to the object IS the value of an object reference
> variable.

That's a bizarre and unnatural way of looking at it. To steal a line from
the effbot, that's like valuing your child's Social Security number over
the child herself:

http://mail.python.org/pipermail/python-list/2003-May/204560.html


If we execute a line of Python code:

x = "parrot"

and then ask "What's the value of x?", I think that even you would think
I was being deliberately obtuse, difficult and obfuscatory if I answered
"location 0xb7cdeb2c".


> So good, parameters are passed ByVal in Python as they appear
> to be, and as is the default in every other modern language.

Nonsense. Python doesn't copy a parameter before passing it to the
function. You get the same parameter inside the function as outside:

>>> def foo(x):
... print id(x)
...
>>> a = ['some', 'thing']
>>> print id(a); foo(a)
3083441036
3083441036


I'm going to anticipate your response here: you're going to deny that
call by value implies that the list ['some', 'thing'] will be copied
before being passed to the function. According to *some* definitions of
CBV, you might even be right. But according to *other* definitions,
including the one that I learned in comp sci at university, that copying
of data is an essential part of CBV.

These other definitions aren't necessarily a formal definition from some
Computer Scientist. They're just as likely to be informal understandings
of what CBV and CBR mean: "if it's call by value, don't pass big data
structures because they will be copied and your code will be slow".


>> Just as assignment transfers the reference to the RHS object to the
>> name
>> shown on the LHS.
>
> Assignment copies the RHS value to the LHS variable. In the case of an
> object reference, the value copied is, er, an object reference.

No, assignment binds an object to a name. That's what Python does.

Of course, at the implementation level, name binding might be implemented
by copying object references. Or it might not. That's an implementation
detail that isn't relevant at the Python level.

Or at least, it shouldn't be relevant until the abstraction leaks.
http://www.joelonsoftware.com/articles/LeakyAbstractions.html

[snip]


> For object references (including the mutable ones that may treat people
> up), Python's behavior is no different from any other language.

That's an exceedingly broad claim. No different from Java? Well, perhaps.
No different from Lisp? Doubtful. No different from Forth? Yeah, riiight.

Speaking of Java, there's one major difference between Java and Python
with respect to names. In a statically typed language like Java, you
define names before you use them, and from that point the name is bound
to both a type and an object. But the binding to the object is optional,
and such unbound names are said to be null.

In a dynamically typed language like Python, names are bound only to
objects. You can't have an unbound name: if a name exists, it must be
bound to an object, and if it doesn't exist, you get a NameError
exception when you try to access it. And objects are typed, not names.

http://www.ferg.org/projects/python_java_side-by-side.html


>>>> (Answer: neither. They are call by name.)
>>>
>>> I have no idea what that means. They're call by value as far as I can
>>> tell. (Even if the value may happen to be a reference.)
>>
>> Technically, as I recall the definition of "call by name", they
>> aren't that either. ...
>> Call by name, then, acted as a macro expansion wherever the argument
>> was referenced in the called function.
>
> Thanks for that explanation. Clearly that's not what's going on in
> Python.

Ah no, that's my bad. I have a strange and disturbing mental stutter that
substitutes "call by name" when I mean to say "call by object" at the
most embarrassing times. Sorry.


--
Steven

Steve Holden

unread,
Oct 19, 2008, 12:40:28 PM10/19/08
to Steven D'Aprano, pytho...@python.org
Steven D'Aprano wrote:
[...]

> when you talk about "call by value
> where the value is a reference", it sounds to me as if you are insisting
> that cars are ACTUALLY horse and buggies, where the horse is the engine,
> why are we inventing new terms like 'automobile', that just confuses
> people.
>

+1 QOTW

Steve Holden

unread,
Oct 19, 2008, 12:40:28 PM10/19/08
to pytho...@python.org, pytho...@python.org
Steven D'Aprano wrote:
[...]

> when you talk about "call by value

> where the value is a reference", it sounds to me as if you are insisting
> that cars are ACTUALLY horse and buggies, where the horse is the engine,
> why are we inventing new terms like 'automobile', that just confuses
> people.
>

Fuzzyman

unread,
Oct 22, 2008, 6:05:40 PM10/22/08
to
On Oct 17, 10:39 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
>
> >> And my real point is that this is exactly the same as in every
> >> other modern language.
>
> > No, it isn't.  In many other languages (C, Pascal, etc.), a
> > "variable" is commonly thought of as a fixed location in memory
> > into which one can put values.  Those values may be references
> > to objects.
>
> Right, though not in languages like C and Pascal that don't HAVE the  
> notion of objects.  We really ought to stop bringing up those  
> dinosaurs and instead compare Python to any modern OOP language.
>
> >  In Python, that's not how it works.  There is no
> > "location in memory" that corresponds to a variable with a
> > particular name the way there is in C or Pascal or Fortran or
> > many other languages.
>
> No?  Is there any way to prove that, without delving into the Python  
> source itself?
>


.NET makes a clear distinction between 'value types' and reference
types. These are analagous to the call by value and call by reference
that have been discussed in this thread.

My understanding of the difference is that value types (all numeric
types, structs, enumerations etc) actually live on the stack, whereas
reference types (strings, classes etc) live in the heap and have a
pointer on the stack.

It is complicated by the fact that .NET perpetuates the myth that the
primitives (the value types) inherit from System.Object (a reference
type). The runtime does auto-boxing for you where this matters.

This means that when you pass a value type into a method the value
*is* copied. Structs can be arbitrarily big, so this can be a
performance problem. It is often a performance win for working with
the numeric types as you remove a level of indirection.

It isn't without problems though - and some of these can be seen in
IronPython.

System.Drawing.Point is a struct, but it is effectively a mutable
value type. However, when you access it you are often accessing a copy
- and if you attempt to mutate it then your changes will be lost.

The following code illustrates the problem:

>>> r = Rectangle(0, 1002 20, 40)
>>> r.Location.X
0
>>> r.Location.X = 20
>>> r.Location.X
0

Because r.Location returns a value type, the update to it is 'lost'.

By this definition Python objects (all of them) are clearly reference
types and not value types.

In .NET you can specify that a parameter to a method takes a reference
('out' in C# or ByRef in VB.NET). If you pass in a value type as a
reference parameter then the .NET runtime will do boxing / unboxing
for you.

This means that we can write code like the following (roughly C#
pseudo code):

int x = 3;
SomeMethod(out x);

x can now be mutated by 'SomeMethod' and can have a different value.

In a 'way' immutable Python types behave a bit like .NET value types,
and mutable types like reference types. As you can see, this analogy
breaks down.

Michael Foord
--
http://www.ironpythoninaction.com/

Douglas Alan

unread,
Oct 27, 2008, 1:45:48 PM10/27/08
to
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:

> I understand that Python's object and calling semantics are exactly the
> same as Emerald (and likely other languages as well), and that both
> Emerald and Python are explicitly based on those of CLU, as described by
> by Barbara Liskov in 1979:
>
> "In particular it is not call by value because mutations of
> arguments performed by the called routine will be visible to the
> caller. And it is not call by reference because access is not
> given to the variables of the caller, but merely to certain
> objects."

It is quite true that Python's calling semantics are the same as
CLU's, and that CLU called these semantics "call by sharing". It's
not quite true that CLU invented these calling semantics, however.
They were the calling semantics of Lisp long before CLU existed. I'm
not sure that Lisp had a name for it, however. Lisp people tended to
refer to all variable assignment as "binding".

I agree with those who object to calling the Python/CLU/Lisp calling
semantics as either "call by value" or "call by reference", which is
why I've been a bit dismayed over the years that the term "call by
sharing" hasn't caught on. When this terminology is used, the meaning is
quite unambiguous.

It should be noted that many other mainstream languages now use call
by sharing. It's not at all the least peculiar to Python. Such
languages include Java, JavaScript, Ruby, C#, and ActionScript.

|>oug

goob...@gmail.com

unread,
Oct 27, 2008, 2:19:41 PM10/27/08
to
On Oct 17, 5:39 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
>
> >> And my real point is that this is exactly the same as in every
> >> other modern language.
>
> > No, it isn't.  In many other languages (C, Pascal, etc.), a
> > "variable" is commonly thought of as a fixed location in memory
> > into which one can put values.  Those values may be references
> > to objects.
>
> Right, though not in languages like C and Pascal that don't HAVE the  
> notion of objects.  We really ought to stop bringing up those  
> dinosaurs and instead compare Python to any modern OOP language.
>
> >  In Python, that's not how it works.  There is no
> > "location in memory" that corresponds to a variable with a
> > particular name the way there is in C or Pascal or Fortran or
> > many other languages.
>
> No?  Is there any way to prove that, without delving into the Python  
> source itself?
>
> If not, then I think you're talking about an internal implementation  
> detail.


I think this "uncontrived" example addresses the C/Python difference
fairly directly (both were tested):
----------------------------------
C:

struct {int a;} s1, s2;

int main()
{
s1.a = 1;
s2 = s1;

printf("s1.a %d s2.a %d\n", s1.a, s2.a);
s1.a = 99;
printf("s1.a %d s2.a %d\n", s1.a, s2.a);
}

----------------------------------
Python:

class mystruct:
pass

s1 = mystruct()
s1.a = 1
s2 = s1

print "s1.a %2d s2.a %2d" % (s1.a,s2.a)
s1.a = 99
print "s1.a %2d s2.a %2d" % (s1.a,s2.a)

---------------
C OUTPUT:
s1.a 1 s2.a 1
s1.a 99 s2.a 1

Python OUTPUT:
s1.a 1 s2.a 1
s1.a 99 s2.a 99

Note that in C (or C++) the value of s2.a remains unchanged, because
the VALUE of s1 (the contents of the memory where s1 resides) was
COPIED to the memory location of s2, and subsequently, only the VALUE
of s2.a was changed. In Python, s2.a is "changed" (but not really)
because it turns out that s2 is just another name for the object that
s1 pointed to.

So there is no programatically accessible "location in memory" that
corresponds to s1 or s2 in Python. There is only a location in memory
that corresponds to the object that s1 is currently pointing to. In C,
by contrast, there are definite locations in memory that correspond to
both variables s1 and s2, and those locations remain always separate,
distinct and unchanged throughout the execution of the program.

This is not an "implementation detail", it is a fundamental part of
each language. As C was an "improvement" on assembler, the variable
names have always just been aliases for memory locations (or
registers). You can see this in the output of any C/C++ compiler.

In Python, variables are just names/aliases for *references* to
objects, not names for the objects/values themselves. The variable
names themselves do not correspond directly to the objects' memory
locations. While yes, technically, it is true that those reference
values must be stored somewhere in memory, *that* is the
implementation detail. But is is not the *locations* of these
references (i.e., the locations of the Python *variables*) that are
copied around, it is the references themselves (the locations of the
Python *objects*) that are copied.

> > All that exists in Python is a name->object mapping.
>
> And what does that name->object mapping consist of?  At some level,  
> there has to be a memory location that stores the reference to the  
> object, right?

I think this is answered above, but just to drive it home, in Python
the memory locations of the variables themselves (an implementation
detail), which hold the references to the objects, are inaccessible .
In C/C++, by contrast, variable names correspond directly to memory
locations and objects, and you can easily find the addresses of
variables.

In C/C++, if you choose, you may have a variable that is itself a
reference/pointer to some other memory/object. In C, we would say that
the VALUE of that variable is the memory address of another object.
But you can, if you need to, get the address of the pointer variable,
which points to the *address* of the other object.

In Python, a variable is ONLY EVER a reference to an object. You
cannot get the address of a Python variable, only of a Python object.

Hope this clears things up.

dale

Dale Roberts

unread,
Oct 27, 2008, 2:49:44 PM10/27/08
to
On Oct 17, 5:39 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
>
> >> And my real point is that this is exactly the same as in every
> >> other modern language.
>
> > No, it isn't. In many other languages (C, Pascal, etc.), a
> > "variable" is commonly thought of as a fixed location in memory
> > into which one can put values. Those values may be references
> > to objects.
>
> Right, though not in languages like C and Pascal that don't HAVE the
> notion of objects. We really ought to stop bringing up those
> dinosaurs and instead compare Python to any modern OOP language.
>
> > In Python, that's not how it works. There is no
> > "location in memory" that corresponds to a variable with a
> > particular name the way there is in C or Pascal or Fortran or
> > many other languages.
>
> No? Is there any way to prove that, without delving into the Python
> source itself?
>
> If not, then I think you're talking about an internal implementation
> detail.


I think this "uncontrived" example addresses the (C/C++)/Python
difference fairly directly.
----------------------------------
C:

----------------------------------
Python:

class mystruct:
pass

> > All that exists in Python is a name->object mapping.


>
> And what does that name->object mapping consist of? At some level,
> there has to be a memory location that stores the reference to the
> object, right?

I think this is answered above, but just to drive it home, in Python


the memory locations of the variables themselves (an implementation
detail), which hold the references to the objects, are inaccessible .
In C/C++, by contrast, variable names correspond directly to memory
locations and objects, and you can easily find the addresses of

variables, and the addresses do not change, although the values can.

In C/C++, if you choose, you may have a variable that is itself a

reference/pointer to some other memory/object/array. In C, we would

Joe Strout

unread,
Oct 27, 2008, 3:11:04 PM10/27/08
to Python List
On Oct 27, 2008, at 12:19 PM, goob...@gmail.com wrote:

> I think this "uncontrived" example addresses the C/Python difference
> fairly directly (both were tested):

That's correct, but of course, C is a decades-old language barely a
step above assembler. For a fair comparison, pick any modern OOP
language, including the C derivatives (C++, Objective-C, Java), and
compare a Python object to an object in that language, rather than to
a struct.

> In Python, variables are just names/aliases for *references* to
> objects, not names for the objects/values themselves. The variable
> names themselves do not correspond directly to the objects' memory
> locations.

Exactly! In C++, this would be like a pointer variable. In Java, RB,
or .NET, it's like an object reference.

> While yes, technically, it is true that those reference
> values must be stored somewhere in memory, *that* is the
> implementation detail.

Agreed. (And this was my point in response to someone arguing that no
such location exists.)

> But is is not the *locations* of these
> references (i.e., the locations of the Python *variables*) that are
> copied around, it is the references themselves (the locations of the
> Python *objects*) that are copied.

Right. The variables contain object references; these object
references are copied (not referenced!) when you pass them into a
function. That's call by value. In the case of an assignment, the
reference is copied.

>>> All that exists in Python is a name->object mapping.
>>
>> And what does that name->object mapping consist of? At some level,
>> there has to be a memory location that stores the reference to the
>> object, right?
>
> I think this is answered above, but just to drive it home, in Python
> the memory locations of the variables themselves (an implementation
> detail), which hold the references to the objects, are inaccessible .

Right. So too in Java, RB, .NET, etc. Pointers are nasty. But lack
of pointers does not change the calling semantics.

> In C/C++, by contrast, variable names correspond directly to memory
> locations and objects, and you can easily find the addresses of
> variables.

Hmm, no, the C++ equivalent of an object reference would be:

SomeClass* foo;

In fact, many C++ programmers prefer to typedef a pointer to each
class, since it's the pointer (which is rough equivalent of a
reference in newer languages) that you almost always want, rather than
the class itself. So it would actually be:

SomeClassPtr foo;

Now, when you do:

foo2 = foo;

you are copying the object reference from foo to foo2, just as in
Python. When you pass it into a function:

void NiftyMethod(SomeClassPtr arg) {...}
...
NiftyMethod(foo);

You are copying the object reference right onto the call stack. This
is pass by value, plain and simple. And because it is pass by value,
you know that nothing NiftyMethod does can possibly change the value
of foo -- that is, can make it point at something else. (It may well
change the data that the object it points to contains, if SomeClass
objects are mutable, but it can't change foo itself.) This is, again,
just like Python and every other OOP language.

Call by reference would be this:

void NiftyMethod2(SomeClassPtr &arg) {...}
...
NiftyMethod2(foo);

Now, arg here is passed by reference (just like a ByRef parameter in
RB or .NET). That means that NiftyMethod2 could very well change the
value that is passed in. It could actually make foo point to
something else.

No Python method can do that, because Python arguments are ALWAYS
passed by value. There is no call by reference in Python. Period,
end of story, nothing to see here.

Cheers,
- Joe

Terry Reedy

unread,
Oct 27, 2008, 6:03:26 PM10/27/08
to pytho...@python.org
goob...@gmail.com wrote:
> On Oct 17, 5:39 pm, Joe Strout <j...@strout.net> wrote:
>> On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:

>>> No, it isn't. In many other languages (C, Pascal, etc.), a
>>> "variable" is commonly thought of as a fixed location in memory
>>> into which one can put values. Those values may be references
>>> to objects.

In particular, memory is a linear sequence of writable cells. In Turing
machines, they have no address, and access is by one-at-a-time movement.
Subsequently, cells were given count addresses 0, 1, 2, ... .

>> Right, though not in languages like C and Pascal that don't HAVE the
>> notion of objects. We really ought to stop bringing up those
>> dinosaurs and instead compare Python to any modern OOP language.
>>
>>> In Python, that's not how it works. There is no
>>> "location in memory" that corresponds to a variable with a
>>> particular name the way there is in C or Pascal or Fortran or
>>> many other languages.
>> No? Is there any way to prove that,

The burden of proof is on those who claim a positive. Grant and I claim
that there is no pink elephant in the room, and that we have looked
around pretty thoroughly. You claim that there is. Show us what we missed.

Anyway, suppose you read and execute "L123 = [1,2,3]". You can, I
presume, perform any list method on that object. Where is it? Some
memory theories say 'distributed, nowhere in particular'. Others say
'concentrated, some particular neurons', but certainly nothing like the
'where' of linear computer memory. Consider another object s = 'boo'.
Which has the lower address?

>> without delving into the Python source itself?

Python, the abstract information algorithm language, has no 'source',
only a specification of syntax and semantics. The CPython source is the
source for a particular computer machine implementation. Any such
implemetation has to map abstractly locationless objects to particular
blocks of computer memory without adding extraneous, Python-accessible
semantics, such as relative position.

>> If not, then I think you're talking about an internal implementation
>> detail.

I think *you* are. Giving Python objects an integer address is an
(optional) implementation detail. Giving them a *fixed* integer address
is an optional CPython detail that makes certain aspects of the code
easier but which prevents re-locating garbage collection (which I
believe Jython does).

Anyone is free to view Python as only a linear-memory computer
programming language (and, in some respects, as that, inferior to C).
However, I have also viewed it as an algorithm language and, as a
beginner (about 10 years ago), quickly dubbed it 'executable pseudocode'
(and in that respect, much superior to C).

Terry Jan Reedy

Steven D'Aprano

unread,
Oct 27, 2008, 6:55:01 PM10/27/08
to
On Mon, 27 Oct 2008 13:11:04 -0600, Joe Strout wrote:

> On Oct 27, 2008, at 12:19 PM, goob...@gmail.com wrote:
>
>> I think this "uncontrived" example addresses the C/Python difference
>> fairly directly (both were tested):
>
> That's correct, but of course, C is a decades-old language barely a step
> above assembler.

So what? It's not like C is no longer in common use.

And even if C had disappeared off the landscape, there are millions of
programmers, including beginning programmers, whose understanding of
terms CBR and CBV are defined by the behaviour of languages like C and
Pascal -- even if they haven't learned either language themselves.


> For a fair comparison, pick any modern OOP language,
> including the C derivatives (C++, Objective-C, Java), and compare a
> Python object to an object in that language, rather than to a struct.

But we already know that many such languages use the exact same calling
convention as Python, so all you would be showing is that languages with
the same calling convention as Python have the same calling convention as
Python.

By common usage and technical definition, C is call by value. Argument
passing in Python does not behave like C. So why insist that Python is
also call by value?

[snip]

>> While yes, technically, it is true that those reference values must be
>> stored somewhere in memory, *that* is the implementation detail.
>
> Agreed. (And this was my point in response to someone arguing that no
> such location exists.)

Obviously any computer which is based on the Von Newman architecture of
CPU plus memory is going to store the reference *somewhere*. That's a
detail unimportant at the Python level. But since clockwork or Conway's
"Life" cellular automata are both Turing complete, it would be possible
to build a Python implementation where the reference values weren't
localised to a particular place in memory, but distributed over the
system.


>> But is is not the *locations* of these references (i.e., the locations
>> of the Python *variables*) that are copied around, it is the references
>> themselves (the locations of the Python *objects*) that are copied.
>
> Right. The variables contain object references; these object references
> are copied (not referenced!) when you pass them into a function. That's
> call by value. In the case of an assignment, the reference is copied.

The value of a Python name is the Python object assigned to it, not an
arbitrary memory location that points to the object. Even you would
consider it obfuscatory if I executed this code:

x = "Norwegian Blue"

and then insisted that the value of x was "3086179808L, but if I run that
line of code again it could get another value, and naturally if you run
it on your computer you're almost certain to get a different value".

By your definition of "value=reference", the above is perfectly correct,
and utterly, completely pointless, useless and unhelpful. It's rather
like listing the ingredients of a cake as "Atoms". Technically true, but
missing the point.

[snip]


> You are copying the object reference right onto the call stack. This is
> pass by value, plain and simple.

Who *cares* about copying the pointers? That's the WRONG LEVEL.
Ultimately EVERY programming language that runs on a computer with memory
is "Copy By Bit Flipping", but it would be useless and unhelpful to tell
people that every programming language uses the exact same calling
conventions: "bits are flipped, and that's the end of story".


[snip]


> No Python method can do that, because Python arguments are ALWAYS passed
> by value. There is no call by reference in Python.

Except that for millions of programmers who have learnt their terminology
from Pascal and C, that implies that the values -- the data itself, not
pointers to the data -- are copied. It implies that this can never fail:

x = [1]
y = function(x)
assert x == [1]

but of course it can fail, if function modifies x -- something which CBV
implies can't happen.

> Period, end of story, nothing to see here.

I think that this entire argument hinges on the poverty of your mental
toolbox. You have a hammer (call by value) and a screwdriver (call by
reference) and refuse to accept that there could possibly be any other
calling model. Hence you force any actual calling model into the
framework of CBV or CBR, no matter how much violence you have to do to
simple terms like "value" to make it fit.


--
Steven

Chuckk Hubbard

unread,
Oct 27, 2008, 7:20:56 PM10/27/08
to pytho...@python.org
I'm sorry to say I'm pretty confused by the example, but if you want
something like

bob = module.object()
frank = module.object()
and then to know that bob is bob from a list of instances, you could
instead do something like:

for person in listofnames:
temp = module.object(person)
list.append(temp)

where the __init__ function assigns the argument to object.nametag or
something. This way you can retrieve the name from an index into the
list, or retrieve the index by searching for the name...
-Chuckk

On Thu, Oct 16, 2008 at 5:04 PM, Astley Le Jasper
<Astley....@gmail.com> wrote:
> On 16 Oct, 16:52, Carsten Haese <carsten.ha...@gmail.com> wrote:
>> Astley Le Jasper wrote:
>> > Sorry for the numpty question ...
>>
>> > How do you find the reference name of an object?
>>
>> > So if i have this
>>
>> > bob = modulename.objectname()
>>
>> > how do i find that the name is 'bob'
>>
>> Why do you need to find that? You know that its name is 'bob'.
>>
>> --
>> Carsten Haesehttp://informixdb.sourceforge.net
>
> I'm creating mulitple instances, putting them in a list, iterating
> through the list to send them to some functions where process them
> with some instance specific parameters. Something along the lines of:
>
> bob = someobject()
> harry = someobject()
> fred = someobject()
>
> parameterdict = {'bob':(0,1,2),'harry':(3,4,5),'fred':(6,7,8)}
> people_list = (bob, harry, fred)
>
> for person in people_list:
> add_parameters(person)
>
> def add_parameters(person)
> mytuple = parameterdict[??????instance.name????]
> person.x = mytuple[0]
> person.y = mytuple[1]
> person.z = mytuple[2]
>
> ... alternatively there is probably a very much easier way of doing
> it.
> --
> http://mail.python.org/mailman/listinfo/python-list
>

--
http://www.badmuthahubbard.com

greg

unread,
Oct 27, 2008, 10:58:10 PM10/27/08
to
Steven D'Aprano wrote:

> By common usage and technical definition, C is call by value. Argument
> passing in Python does not behave like C. So why insist that Python is
> also call by value?

Whether it behaves like C is not the test.

Let's look at the definitions of the terms:

(1) Call by value: The actual parameter is an expression. It is
evaluated and the result is assigned to the formal parameter.
Subsequent assignments to the formal parameter do not affect
the actual parameter.

(2) Call by reference: The actual parameter is an lvalue. The
formal parameter becomes an alias for the actual parameter,
so that assigning to the formal parameter has the same
effect as assigning to the actual parameter.

Seems to me that (1) describes exactly how parameter passing
works in Python. So why insist that it's *not* call by value?

--
Greg

Dale Roberts

unread,
Oct 27, 2008, 11:16:04 PM10/27/08
to
[I am actually enjoying this discussion, even though it does not address
the OP's question. It is helping to solidify *my* understanding.]

Joe Strout wrote:
> On Oct 27, 2008, at 12:19 PM, goob...@gmail.com wrote:
>
>> I think this "uncontrived" example addresses the C/Python difference
>> fairly directly (both were tested):
>
> That's correct, but of course, C is a decades-old language barely a step
> above assembler. For a fair comparison, pick any modern OOP language,
> including the C derivatives (C++, Objective-C, Java), and compare a
> Python object to an object in that language, rather than to a struct.

Okay, sorry, should have had C++ from the start. See my spiffed-up
example here, where I magically convert to C++ by replacing "struct"
with "class" and adding the word "public:". Still behaves the same, though.

I added the functions ByVal() and ByRef() to show that when you pass by
value, the contents of the object cannot be changed. This is not
possible in Python unless a copy of the object is made (which is what
C++ does automatically for you in pass-by-value).

In Python, the contents of the object are changed, which is most similar
to the pass by reference (or by pointer) construct in C++. But, yes, as
you say, technically:

passing the object by reference
== passing the address of the object by value.

But I think that is, to most programmers, a surprising use of the term
"pass by value".

And note in my example, nowhere do I explicitly take the address of s1.
The compiler does this for me in the ByRef() case. And nowhere to I make
a copy of s1. Again, the compiler does this for me in the ByVal() case.
The calls to ByVal() and ByRef() are identical. You cannot tell from the
calls which thing is going to happen.

-----------------------
class MyClass {public: int a;} s1, s2;

void ByVal(MyClass obj) {obj.a=42;}
void ByRef(MyClass &obj) {obj.a=43;}

int main()
{
s1.a = 1;
s2 = s1;

printf("s1.a %2d s2.a %2d\n", s1.a, s2.a);

s1.a = 99;
printf("s1.a %2d s2.a %2d\n", s1.a, s2.a);

ByVal(s1);
printf("s1.a %2d\n", s1.a);

ByRef(s1);
printf("s1.a %2d\n", s1.a);
}
--------------
class mystruct:
pass

def ByObject(obj): obj.a=42

s1 = mystruct()
s1.a = 1
s2 = s1

print "s1.a %2d s2.a %2d" % (s1.a,s2.a)
s1.a = 99
print "s1.a %2d s2.a %2d" % (s1.a,s2.a)

ByObject(s1)
print "s1.a %2d" % (s1.a)

--------------
C++ OUTPUT
s1.a 1 s2.a 1
s1.a 99 s2.a 1 # note s2.a does not change when s1.a is modified
s1.a 99 # contents of s1.a does not change when passed by val
s1.a 43 # it does change when passed by ref

Python OUTPUT
s1.a 1 s2.a 1

s1.a 99 s2.a 99 # s2.a "changes" because it's the same object as s1
s1.a 42 # Contents of object does change with function call.

...and in Python, of course, as you say, what you call the "value" of
s1, the address of the object, id(val), does not change.

>>
>> [skipping lots of stuff we agree on!]


>>
>> In C/C++, by contrast, variable names correspond directly to memory
>> locations and objects, and you can easily find the addresses of
>> variables.
>
> Hmm, no, the C++ equivalent of an object reference would be:
>
> SomeClass* foo;

Whoah, nonsequitor there. Let's back up. I did not use the word
"reference", and that is the point. And I am correct that C variable
names correspond to memory locations (or sometimes CPU registers -
optimizers can really mangle things). And you can get the addresses of
the variables themselves using the & operator.

Have a look at my example code again. s1 and s2 ARE OBJECTS THEMSELVES,
they are not references to objects. You can do this in C++ (not in
Python). You can pass whole objects, by value (they are copied by the
compiler), on the stack. And we both understand that you can't do that
in Python. That is why we differentiate between "pass by reference" and
"pass by value" in C++, and people generally understand what that means.

> ...


> void NiftyMethod2(SomeClassPtr &arg) {...}
> ...
> NiftyMethod2(foo);
>
> Now, arg here is passed by reference (just like a ByRef parameter in RB
> or .NET). That means that NiftyMethod2 could very well change the value
> that is passed in. It could actually make foo point to something else.
>
> No Python method can do that,

Yes, absolutely agreed. A Python method can never change *which* object
the caller points to, it can only change the *contents* of that object.

But the same is true in C++ as well. In your example, the address of the
foo variable itself can never be changed. You can change the *value* of
foo (so it points to a different object), or you can change the contents
of the object foo points to. foo is a variable with an address which you
can usually see with a printf("%x", &foo), and that is different from
the address of the object which you get when you say printf("%x", foo).

The value &foo cannot be changed.

> because Python arguments are ALWAYS passed
> by value. There is no call by reference in Python. Period, end of
> story, nothing to see here.

Yea, BUT... If you tell this to a C++ programer without any further
explanation, they will be thoroughly confused and misinformed, unless
you point them to this thread or amend that statement with your version
of what "pass by value" means. I know what you mean, and you know what I
mean, but that's because we've both read through this thread ;-)

Look at my example. The ByVal() routine behaves how C++ programmers
expect "pass by value" to work. The contents of the caller's object
cannot be modified.

So, then, what to tell a C++ programmer about how Python passes
arguments? You say: tell them Python only passes by value. I disagree,
because I think that would confuse them. Rather than try to map C++
conventions onto Python, I think it is more useful to just tell them how
it really works. Maybe a few statements like this:

All values in Python are objects, from simple integers up to complex
user-defined classes.

An assignment in Python binds a variable name to an object. The
internal "value" of the variable is the memory address of an object,
and can be seen with id(var), but is rarely needed in practice.

The "value" that gets passed in a Python function call is the address
of an object (the id()).

When making a function call, myfunc(var), the value of id(var) can
never be changed by the function.

Not sure if these are the best. To get into much more detail, you have
to start explaining mutable and immutable objects and such.

dale


> Cheers,
> - Joe

Douglas Alan

unread,
Oct 28, 2008, 12:14:23 AM10/28/08
to
greg <gr...@cosc.canterbury.ac.nz> writes:

> Seems to me that (1) describes exactly how parameter passing
> works in Python. So why insist that it's *not* call by value?

Because there's an important distinction to be made, and the
distinction has been written up in the Computer Science literature
since Lisp first starting using the same argument passing semantics as
Python back in 1958. The semantics are called "call by sharing".

Many mainstream programming languages other than Python now use call
by sharing. They include Java, JavaScript, Ruby, ActionScript, and C#.

|>oug

P.S. Lisp didn't call it "call by sharing" -- Lisp called it
"binding". The designers of CLU invented the term "call by sharing"
back in the 70s. (Or at least I believe they invented the term. They
certainly did use the term.)

Gabriel Genellina

unread,
Oct 28, 2008, 1:28:16 AM10/28/08
to pytho...@python.org
En Tue, 28 Oct 2008 00:58:10 -0200, greg <gr...@cosc.canterbury.ac.nz>
escribió:

Those definitions are only applicable to unstructured, primitive types,
where the only relevant operations are "get value" and "assign value".
Structured types provide other operations too - like selection (attribute
get/set in Python). It is unspecified on both definitions above what
happens in those cases. Other posts in this same thread showed that Python
behaves similarly to call-by-reference in C++ with regard to data members
inside a structure (that is, mutable objects *can* be changed, and the
caller sees the change). Combined with your previous conclusion that
Python implements call-by-value, one should finally conclude that it can't
be neither cbv nor cbr - it's a different thing.
The term "call by object" was coined in the late '70s to describe this
behavior. More info about this ever-recurring topic can be found at
http://effbot.org/zone/call-by-object.htm

--
Gabriel Genellina

Gabriel Genellina

unread,
Oct 28, 2008, 2:33:26 AM10/28/08
to pytho...@python.org
En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <goob...@gmail.com>
escribió:

> So, then, what to tell a C++ programmer about how Python passes
> arguments? You say: tell them Python only passes by value. I disagree,
> because I think that would confuse them. Rather than try to map C++
> conventions onto Python, I think it is more useful to just tell them how
> it really works. Maybe a few statements like this:
>
> All values in Python are objects, from simple integers up to complex
> user-defined classes.
>
> An assignment in Python binds a variable name to an object. The
> internal "value" of the variable is the memory address of an object,
> and can be seen with id(var), but is rarely needed in practice.
>
> The "value" that gets passed in a Python function call is the address
> of an object (the id()).
>
> When making a function call, myfunc(var), the value of id(var) can
> never be changed by the function.
>
> Not sure if these are the best. To get into much more detail, you have
> to start explaining mutable and immutable objects and such.

I don't think the above explanation is desirable, nor needed. Objects in
Python don't have an "address" - it's just a CPython implementation
detail. The fact that id() returns that address is just an implementation
detail too. The calling mechanism should be explained without refering to
those irrelevant details.

--
Gabriel Genellina

Joe Strout

unread,
Oct 28, 2008, 11:59:57 AM10/28/08
to Python List
On Oct 27, 2008, at 11:28 PM, Gabriel Genellina wrote:

> En Tue, 28 Oct 2008 00:58:10 -0200, greg
> <gr...@cosc.canterbury.ac.nz> escribió:
>

>> Let's look at the definitions of the terms:
>>
>> (1) Call by value: The actual parameter is an expression. It is
>> evaluated and the result is assigned to the formal parameter.
>> Subsequent assignments to the formal parameter do not affect
>> the actual parameter.
>>
>> (2) Call by reference: The actual parameter is an lvalue. The
>> formal parameter becomes an alias for the actual parameter,
>> so that assigning to the formal parameter has the same
>> effect as assigning to the actual parameter.
>>
>> Seems to me that (1) describes exactly how parameter passing
>> works in Python. So why insist that it's *not* call by value?

Greg is right on the money here. It really is as simple as that.

> Those definitions are only applicable to unstructured, primitive
> types, where the only relevant operations are "get value" and
> "assign value".

Nonsense. They apply to any type. See here for an introduction to
the topic in VB.NET:

http://www.homeandlearn.co.uk/net/nets9p4.html

The example shown uses an Integer, but guess what -- you can pass ANY
type either ByRef or ByVal, including object references (which are, of
course, quite common in VB.NET). The default is ByVal, which means
that (as in Python) the actual parameter is an expression, and no
assignments to it can affect the actual parameter. It DOES NOT MATTER
that both the formal parameter and the actual parameter may refer to
the same object, and if that object is mutable, you can mutate that
object.

But ByRef is another option, and if you pass an object reference
ByRef, then the formal parameter is an alias for the actual parameter,
and assignments to it change the actual parameter. Python doesn't
have this feature (nor much need for it, given its other features,
like tuple packing/unpacking). So, parameter passing in ByRef is
clearly exactly the same as the default "ByVal" parameter passing in
VB.NET... as well as Java, RB, C++ (when you remember that an object
reference in modern languages is like a pointer in C++), and every
other OOP language I've looked into.

Some of those languages, like Python, don't have different modes, and
so the language designers had no call to give their one mode a name.
So let's look at those that did have such a need, like VB.NET and
REALbasic. What's the default mode called? Why, it's "ByVal". Even
when that value is an object reference. This is short for "by value"
-- it's not short for "by sharing" or "by object" or any other such
silliness. No such terms are needed.

There are only the two cases, which Greg quite succinctly and
accurately described above. One is by value, the other is by
reference. Python quite clearly uses by value. Parameters are
expressions that are evaluated, and the resulting value copied into
the formal parameter, pure and simple. The continued attempts to
obfuscate this is pointless and wrong.

Best,
- Joe


Dale Roberts

unread,
Oct 28, 2008, 12:56:05 PM10/28/08
to
On Oct 28, 2:33 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <goobe...@gmail.com>  


I agree that it was a feeble and ill-advised attempt, and would like
to strike those lines from the record...

But the rest of the post is strong and accurate, I think, and coming
from a mainly C/C++ background, visualizing these object references
being passed around does help improve my understanding of Python's
*behavior* (and it apparently helps Joe too).

[May I refer to you as "Joe The Programmer" in my rhetoric? Are you a
"licensed" programmer making over $250K/year? ;-)]

If asked by a C++ programmer about Python's argument passing, I will
go with the Pass By Object explanation (which is why I called my
Python routine above ByObject()). Although there will be more
'splaining to do, at least it will give the C++ programmer pause, and
help them realize that there is something a little different that they
need to stop and try to understand.

If I just say "Python is Pass By Value, Period" without further
explanation, they will expect things to work as in my ByValue()
example above (where the caller's object contents cannot be changed),
and that is incorrect. And they may go and tell someone else, without
the detailed explanation, that "Dale says it's Pass By Value", and
I'll get blamed when their function surprisingly changes the contents
of the caller's object.

If I just say "Python is Pass By Reference", that is wrong too. As Joe
The Programmer points out, they will expect that the calling
*variable* itself can be changed, and that is wrong too.

They need to understand that Python does not map neatly, directly, and
completely to their C++ experience of Pass By Value (which involves
copying a variable), or Pass By Reference (which involves taking the
address of a variable).

The Key Concept in for a C++ programmer looking at Python is that,
unlike in C++, **Variables Cannot "Contain" Values**. All values in
Python are objects, and all variables in Python simply point to, or
are bound to, or refer to, these objects. The variables themselves do
not contain the objects - if you must (like Joe the Programmer), you
can say that all Python variables *contain* an object reference, and
it is these references that are passed around. Unlike C++, an object
reference is the ONLY thing that a Python variable can contain. A
function parameter is always passed as a reference to an object, not a
reference to a variable, or a copy of a variable or object.

And that is where the confusion arises. When people say ByRef or
ByVal, they usually mean by Reference to (address) or Value of (copy)
the *contents* of the passed variable. But, PYTHON VARIABLES DO NOT
"CONTAIN" VALUES (sorry for the shouting, but it is the most important
point here), so ByRef and ByVal lose their commonly accepted meanings.

In C++, ByValue requires a copy (and Python does not copy). In C++,
ByReference requires the address of a *variable* (an "lvalue"), and
variables do not have accessible addresses in Python.

ByObject, in contrast, requires neither (unless, like Joe The
Programmer, you consider the "value" of a variable to be the id(),
which is not what most people expect when they say "x=5" - they expect
the "value" to be 5). ByObject simply passes an object reference. Nice
and neat.

I think with that explanation (avoiding any mention of memory, or
object id's) will help them understand things better.

As you point out, this is a very old topic, but I guess each newcomer
to Python has to figure it out. The effbot's article you mention are
very helpful, and much of this thread is just a rehash of what he has
long ago spelled out very clearly.

But I am happy to add the strong C++ slant, since that is what I
understand best.

I like either "Call By Object", or "Call By Object Reference", the
latter of which is what Joe The Programmer seems to like, but insists,
confusingly, on rebinding it to the name "call by value".

dale

Dale Roberts

unread,
Oct 28, 2008, 3:44:37 PM10/28/08
to
On Oct 28, 11:59 am, Joe Strout <j...@strout.net> wrote:
> ...

>
> There are only the two cases, which Greg quite succinctly and  
> accurately described above.  One is by value, the other is by  
> reference.  Python quite clearly uses by value.  Parameters are  
> expressions that are evaluated, and the resulting value copied into  
> the formal parameter, pure and simple.  The continued attempts to  
> obfuscate this is pointless and wrong.
>
> Best,
> - Joe

5 + 3

What is the "value" of that expression in Python? Can you tell me?

99.99% of programmers (who do not have this thread as context) will
say that the value is 8. But you say the value is the memory address
of the resulting object created when the + operator is applied to the
5 object and the 3 object. That is the "value" that is copied.

Okay, you can have it that way, but every time you explain to someone
that Python passes "By Value", you will have to add the additional
baggage that, oh, by the way, there is a completely different meaning
for "value" in Python than what you are used to.

Then the questions and puzzled looks will start...

And when they tell their friend that Joe The Programmer said it's Pass
By Value, your additional context may not be present any longer, and
the friend will be very confused.

In my opinion, best just to head it off and call it something
different so as not to confuse.

dale

Aaron Brady

unread,
Oct 28, 2008, 5:43:29 PM10/28/08
to
On Oct 27, 2:11 pm, Joe Strout <j...@strout.net> wrote:

snip.

What do you propose the name of the method of passing parameters
should be for the following function 'f' in C?

struct T {
int a;
int b;
int c;
};

void f( T t );

Given a 4-byte system word, how many bytes do you think are copied to
the stack upon calling 'f'?

Steven D'Aprano

unread,
Oct 28, 2008, 6:31:53 PM10/28/08
to
On Tue, 28 Oct 2008 09:59:57 -0600, Joe Strout wrote:

> There are only the two cases, which Greg quite succinctly and accurately
> described above. One is by value, the other is by reference. Python
> quite clearly uses by value.

That is absolute nonsense, based on the idiotic assumption that
programmers should care more about an arbitrary reference to a value than
to the value itself.

I'm sure I've quoted the excellent effbot before, but he deserves
repeating:

[quote]
well, I guess you can, in theory, value an artificial number assigned
to an object as much as the object itself.

"Joe, I think our son might be lost in the woods"
"Don't worry, I have his social security number"
[end quote]

As I wrote yesterday:

The value of a Python name is the Python object assigned to it, not an
arbitrary memory location that points to the object. Even you would
consider it obfuscatory if I executed this code:

x = "Norwegian Blue"

and then insisted that the value of x was "3086179808L, but if I run that
line of code again it could get another value, and naturally if you run
it on your computer you're almost certain to get a different value".

By your definition of "value=reference", the above is perfectly correct,
and utterly, completely pointless, useless and unhelpful. It's rather
like listing the ingredients of a cake as "Atoms". Technically true, but
missing the point.

Once we discard the unhelpful assumption that value=reference, your
entire argument falls apart.

--
Steven

Douglas Alan

unread,
Oct 29, 2008, 1:25:03 AM10/29/08
to
Joe Strout <j...@strout.net> writes:

> There are only the two cases, which Greg quite succinctly and
> accurately described above. One is by value, the other is by
> reference. Python quite clearly uses by value.

You make a grave error in asserting that there are only two cases.
Algol, for instance, used call-by-name, which is neither call-by-value
or call-by-reference. There are a number of other evaluation
strategies. For a primer on the subject see the following Wikipedia
page:

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

CLU used the termed "call-by-sharing" for the evaluation strategy
shared by Python, Lisp, CLU, Java, Ruby, and JavaScript, etc.

It should be noted that the Wikipedia page does not document
"call-by-sharing", in specific and refers to Python's strategy as a
type of call-by-value. It also notes that call-by-value is not a
single evaluation strategy, but rather a family of evaluation
strategies, and that the version of the strategy used by Java (and
hence Python) shares features with call-by-reference strategies.

Consequently, many people prefer to use a different name from
"call-by-value" for Python/Java/Lisp's strategy in order to avoid
confusion. In any case, no one can disagree with the fact that the
evaluation strategy used by Python et. al., differs significantly from
the call-by-value evaluation strategy used by C and the like, whatever
you wish to call it.

|>oug

Antoon Pardon

unread,
Oct 29, 2008, 6:38:54 AM10/29/08
to
On 2008-10-17, Joe Strout <j...@strout.net> wrote:

>> Python's assignment semantics (as opposed to its "object handling, a
>> term for which I have no referent) are not the same as those of, say
>> C.
>
> They are, though. The only difference you've pointed out is that
> *numbers* are different in Python vs. C, and that's an internal
> implementation detail I was blissfully unaware of until this
> discussion. (I'm grateful to know it, but it really doesn't matter in
> day-to-day coding.)

No they are not. An assignment in Python is like making an (new) alias/reference,
while an asignment in C is copying the content of one variable into another.

--
Antoon Pardon

Grant Edwards

unread,
Oct 29, 2008, 9:28:43 AM10/29/08
to

That's been pointed out over and over and over, but some people
seem unable or unwilling to grasp the difference.

--
Grant Edwards grante Yow! Someone in DAYTON,
at Ohio is selling USED
visi.com CARPETS to a SERBO-CROATIAN

Dale Roberts

unread,
Oct 29, 2008, 11:27:07 AM10/29/08
to
On Oct 28, 11:59 am, Joe Strout <j...@strout.net> wrote:
> ...
>
> There are only the two cases, which Greg quite succinctly and  
> accurately described above.  One is by value, the other is by  
> reference.  Python quite clearly uses by value.  Parameters are  
> expressions that are evaluated, and the resulting value copied into  
> the formal parameter, pure and simple.  The continued attempts to  
> obfuscate this is pointless and wrong.
>
> Best,
> - Joe

Joe, you are being too generous and expansive here.

[Play along with me for a minute here...]

Don't you know? There is really only *ONE* case, and, you are right,
it is Pass By Value. There is no such thing as Pass By Reference at
the physical CPU level at all, right? If there is, show it to me. Pass
By Reference is just a silly idiom developed by high-minded CS
academics to confuse the rest of us. It has no practical use and
should not be given its own name, when we already have a good an
proper name for it.

Let me demonstrate with 3 examples of a function definition, and the
appropriate calling syntax for that function in C++, all sharing the
common "int i" global variable:

int i = 5;

myfunc(int &val){} /*CALL:*/ myfunc(i); // "ByRef" (ya, right!)
myfunc(int val){} /*CALL:*/ myfunc(i); // ByVal
myfunc(int *val){} /*CALL:*/ myfunc(&i); // Joe's ByVal

The first is what all the fakers call "Pass By Reference" - sheesh,
how naive. We all know that what *really* happens internally is that
the *address* of val (A VALUE itself, or course) is copied and passed
on the stack, right? There couldn't be a more straightforward example
of Pass By Value (unless it's an inline function, or optimized away,
or possibly when implemented in a VM, or...). It passes the *address*
of i by value, then we can access the *value* of i too via
indirection. Hmm, did we need to have two definitions of VALUE there?
Well, never mind, no one will notice...

The next is obviously pass by value. It's right out there. The value
of i (which is what we are talking about, right?) is copied out, and
passed right on the stack in plain daylight where we can all see it.

How about the third? Pass By Value, obviously, of course. This is the
version you are defending, right? The parameter's value, &i, is
evaluated and copied right onto the stack, just like in the first
example. In fact, if you compare the assembler output of the first and
third examples, you may not even see a difference. Never mind the
actual contents of that pesky "i" variable that most people are
referring to when they use the term "value". We don't need to dress up
example 3 and call it an "idiom" where we are really passing a so-
called "reference" of the variable "i". Indeed! Don't insult our
intelligence. We can all see that it's an address passed by value,
plain and simple.


Pass By Reference? So "postmodern". Who needs it. Show me a so-called
"reference". I've looked at the assembler output and have never seen
one. There is no such thing.

"The continued attempts to obfuscate this is pointless and wrong."


---------------
I hate to have to add this, but for those not paying close attention:

;-)

dale

(tongue back out of cheek now)

Chuckk Hubbard

unread,
Oct 29, 2008, 5:59:46 PM10/29/08
to pytho...@python.org

You are so right! We also don't need "object-oriented programming".
I looked at the motherboard and I don't see any objects moving around!
I don't see any values being passed, either.
When I turn on the TV and see Chuck Norris, though, I know it's only a
reference to Chuck Norris, or I would be blinded. The only case he
needs is "Pass By Roundhouse Kick".

-Chuckk


--
http://www.badmuthahubbard.com

Fuzzyman

unread,
Oct 29, 2008, 6:52:33 PM10/29/08
to
On Oct 28, 3:59 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 27, 2008, at 11:28 PM, Gabriel Genellina wrote:
>
>
>
> > En Tue, 28 Oct 2008 00:58:10 -0200, greg  
> > <g...@cosc.canterbury.ac.nz> escribió:

You're pretty straightforwardly wrong. In Python the 'value' of a
variable is not the reference itself. If that sentence has any meaning
for Python then the value is the object itself.

.NET does draw a distinction between 'value types' and reference types
- where using reference types are called by reference (the reference
is passed) and value types are called by value (the value itself is
copied).

Value types (all numeric types, structs, enumerations etc) actually


live on the stack, whereas reference types (strings, classes etc) live
in the heap and have a
pointer on the stack.

It is complicated by the fact that .NET perpetuates the myth that the
primitives (the value types) inherit from System.Object (a reference
type). The runtime does auto-boxing for you where this matters.

This means that when you pass a value type into a method the value
*is* copied. Structs can be arbitrarily big, so this can be a
performance problem. It is often a performance win for working with
the numeric types as you remove a level of indirection.

It isn't without problems though - and some of these can be seen in
IronPython.

System.Drawing.Point is a struct, but it is effectively a mutable
value type. However, when you access it you are often accessing a copy
- and if you attempt to mutate it then your changes will be lost.

The following code illustrates the problem:

>>> r = Rectangle(0, 1002 20, 40)
>>> r.Location.X
0
>>> r.Location.X = 20
>>> r.Location.X

0

Because r.Location returns a value type (a Point), the update to it is
'lost'.

By this definition Python objects (all of them) are clearly reference

ypes and not value types.

In .NET you can specify that a parameter to a method takes a reference
('out' in C# or ByRef in VB.NET). If you pass in a value type as a
reference parameter then the .NET runtime will do boxing / unboxing
for you.

This means that we can write code like the following C#:

int x = 3;
SomeMethod(out x);

The value of x can be changed by 'SomeMethod' and can have a different
value - something that can't happen in Python.

In a 'way' immutable Python types behave a bit like .NET value types,
and mutable types like reference types. As you can see, this analogy
breaks down.

> But ByRef is another option, and if you pass an object reference  

Steven D'Aprano

unread,
Oct 29, 2008, 6:58:14 PM10/29/08
to
On Wed, 29 Oct 2008 08:27:07 -0700, Dale Roberts wrote:

> On Oct 28, 11:59 am, Joe Strout <j...@strout.net> wrote:
>> ...
>>
>> There are only the two cases, which Greg quite succinctly and
>> accurately described above.  One is by value, the other is by
>> reference.  Python quite clearly uses by value.  Parameters are
>> expressions that are evaluated, and the resulting value copied into the
>> formal parameter, pure and simple.  The continued attempts to obfuscate
>> this is pointless and wrong.
>>
>> Best,
>> - Joe
>
> Joe, you are being too generous and expansive here.
>
> [Play along with me for a minute here...]
>
> Don't you know? There is really only *ONE* case, and, you are right, it
> is Pass By Value. There is no such thing as Pass By Reference at the
> physical CPU level at all, right? If there is, show it to me. Pass By
> Reference is just a silly idiom developed by high-minded CS academics to
> confuse the rest of us. It has no practical use and should not be given
> its own name, when we already have a good an proper name for it.

[snip]

But Dale, you're wrong. At the physical CPU level, there's no copying of
bits at all. If we could copy bits, then we could start with 512MB of RAM
and say "copy all the bits" and end up with 1GB of RAM. So-called copying
is actually just bit-flipping.

So anyone who talks about copying parameters is talking nonsense. There
is no "pass by value". It's all pass by bit-flipping.

--
Steven

Joe Strout

unread,
Oct 29, 2008, 9:13:09 PM10/29/08
to Python List
On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:

> You're pretty straightforwardly wrong. In Python the 'value' of a
> variable is not the reference itself.

That's the misconception that is leading some folks around here into
tangled nots of twisty mislogic, ultimately causing them to make up
new terms for what every other modern language is perfectly happy
calling Call-By-Value.

I've thought a lot about why this misconception is so widespread here,
and I think it must be one of the following:

1. There was one community leader with this idea, who has been
successful at promoting it widely, much to the detriment of all; or,

2. Because everything in Python is an object, you're not forced to
think clearly (and more generally) about references as values as you
are in languages (such as Java, VB.NET, etc.) which have both simple
types and object types.

Either way, it's wrong (or at least, a needlessly complicated way of
looking at things).

> .NET does draw a distinction between 'value types' and reference types
> - where using reference types are called by reference (the reference
> is passed) and value types are called by value (the value itself is
> copied).

Quite right. Now, note that "ByRef" and "ByVal" apply to both.
Generalize to Python. There you go.

Best,
- Joe

P.S. I really am trying to quit responding to this thread. Sometimes
the urge is too strong. But I'll keep trying!

Steve Holden

unread,
Oct 30, 2008, 12:50:26 AM10/30/08
to pytho...@python.org
Joe Strout wrote:
> On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:
>
>> You're pretty straightforwardly wrong. In Python the 'value' of a
>> variable is not the reference itself.
>
> That's the misconception that is leading some folks around here into
> tangled nots of twisty mislogic, ultimately causing them to make up new
> terms for what every other modern language is perfectly happy calling
> Call-By-Value.
>
I tried hard to make myself believe that the above was a clever pun and
knot [sic] a typo. Sadly I failed.

> I've thought a lot about why this misconception is so widespread here,
> and I think it must be one of the following:
>
> 1. There was one community leader with this idea, who has been
> successful at promoting it widely, much to the detriment of all; or,
>
> 2. Because everything in Python is an object, you're not forced to think
> clearly (and more generally) about references as values as you are in
> languages (such as Java, VB.NET, etc.) which have both simple types and
> object types.
>

How about

3. You just hate being wrong.

> Either way, it's wrong (or at least, a needlessly complicated way of
> looking at things).
>

One that has apparently served for almost twenty years now.

>> .NET does draw a distinction between 'value types' and reference types
>> - where using reference types are called by reference (the reference
>> is passed) and value types are called by value (the value itself is
>> copied).
>

> Quite right. Now, note that "ByRef" and "ByVal" apply to both.
> Generalize to Python. There you go.
>
> Best,
> - Joe
>
> P.S. I really am trying to quit responding to this thread. Sometimes
> the urge is too strong. But I'll keep trying!
>

We must tax your patience dreadfully. I have suffered from the same
myself, but I fear we are doomed to pursue each other until Godwin's law
releases us.

Which reminds me, had you thought about submitting a paper along these
lines to PyCon? If we meet at PyCon at least let me buy you a pint to
show there are no hard feelings.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Fuzzyman

unread,
Oct 30, 2008, 7:59:11 AM10/30/08
to
On Oct 30, 1:13 am, Joe Strout <j...@strout.net> wrote:
> On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:
>
> > You're pretty straightforwardly wrong. In Python the 'value' of a
> > variable is not the reference itself.
>
> That's the misconception that is leading some folks around here into
> tangled nots of twisty mislogic, ultimately causing them to make up
> new terms for what every other modern language is perfectly happy
> calling Call-By-Value.
>
> I've thought a lot about why this misconception is so widespread here,
> and I think it must be one of the following:
>
> 1. There was one community leader with this idea, who has been
> successful at promoting it widely, much to the detriment of all; or,
>
> 2. Because everything in Python is an object, you're not forced to
> think clearly (and more generally) about references as values as you
> are in languages (such as Java, VB.NET, etc.) which have both simple
> types and object types.
>


But those languages clearly make the distinction between values and
references that you refuse to make! Go figure...

Michael

Fuzzyman

unread,
Oct 30, 2008, 8:12:08 AM10/30/08
to
On Oct 30, 1:13 am, Joe Strout <j...@strout.net> wrote:
> On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:
>
> > You're pretty straightforwardly wrong. In Python the 'value' of a
> > variable is not the reference itself.
>
> That's the misconception that is leading some folks around here into
> tangled nots of twisty mislogic, ultimately causing them to make up
> new terms for what every other modern language is perfectly happy
> calling Call-By-Value.
>
> I've thought a lot about why this misconception is so widespread here,
> and I think it must be one of the following:
>
> 1. There was one community leader with this idea, who has been
> successful at promoting it widely, much to the detriment of all; or,
>
> 2. Because everything in Python is an object, you're not forced to
> think clearly (and more generally) about references as values as you
> are in languages (such as Java, VB.NET, etc.) which have both simple
> types and object types.
>


To make it clearer for you, call by value means that the value is
copied in - and therefore changes to the value won't be visible to the
caller.

In .NET this is true of mutable value types - changes made are made to
a copy and not visible to the caller. In Python we *only* have
reference types, so changes to *any* mutable object are visible to the
caller.

In .NET you can call by reference with a value type - and the runtime
does boxing for you so that you can see the changes. You have to
explicitly ask for call by reference though.

Michael

Dale Roberts

unread,
Oct 30, 2008, 9:56:12 AM10/30/08
to
On Oct 29, 9:13 pm, Joe Strout <j...@strout.net> wrote:
> On Oct 29, 2008, at 4:52 PM, Fuzzyman wrote:
>
> > You're pretty straightforwardly wrong. In Python the 'value' of a
> > variable is not the reference itself.
>
> That's the misconception that is leading some folks around here into  
> tangled nots of twisty mislogic, ultimately causing them to make up  
> new terms for what every other modern language is perfectly happy  
> calling Call-By-Value.

Doesn't this logic also apply to Call By Reference? Isn't that term
redundant too? (see my 3 C++ examples above). If not, why not? Are you
saying that C++ is capable of using the Call By Reference idiom, but C
is not, because C does not have a reference designation for formal
function parameters?

"Call By Object Reference" is an idiom, just like Call By Reference.
It is not a physical description of what is going on internally at the
register/stack level (which is always just shuffling values around -
or flipping bits, as Steven points out), it is a higher level concept
that helps people understand the *intention* (not necessarily the
implementation) of the mechanism.

You cannot look a C++ programmer straight in the eye and say that
"Python uses Call By Value, Period", without also informing them that
"Python variables can ONLY EVER hold object references - that is the
only "value" they can ever hold". Then the C++ programmer will go "Oh,
yea, that makes sense".

Instead of having to say all of that, we just give it a new name.
Instead of "Call By Value, Where Every Single Value Is Only Ever A
Reference To An Object Which Contains The Actual Value That
Programmers Usually Refer To", we just say "Call By Object Reference".

> ...


> 2. Because everything in Python is an object, you're not forced to  
> think clearly (and more generally) about references as values

I think we've shown that we are all in fact thinking clearly about it,
and we all (you included, of course!) understand what is going on.
It's just a matter of what words we choose to describe it.

Using your definition of value, though, I believe that if you want to
throw out Call By Object Reference, you also have to throw out Call By
Reference. See my 3 C++ examples above. And just for fun I did look at
the assembler output, and, indeed, the output for examples 1 and 3 is
absolutely identical. They are the same thing, as far as the CPU is
concerned.

Would you give them different names?

dale

Joe Strout

unread,
Oct 30, 2008, 11:03:42 AM10/30/08
to Dale Roberts, pytho...@python.org
On Oct 30, 2008, at 7:56 AM, Dale Roberts wrote:

>> That's the misconception that is leading some folks around here into
>> tangled nots of twisty mislogic, ultimately causing them to make up
>> new terms for what every other modern language is perfectly happy
>> calling Call-By-Value.
>
> Doesn't this logic also apply to Call By Reference? Isn't that term
> redundant too? (see my 3 C++ examples above). If not, why not?

It's not. Wikipedia explains the difference pretty well.

> Are you saying that C++ is capable of using the Call By Reference
> idiom,
> but C is not, because C does not have a reference designation for
> formal
> function parameters?

It's been a LONG time since I did anything in C, but yes, I believe
that reference parameters were an addition that came with C++.

> "Call By Object Reference" is an idiom, just like Call By Reference.
> It is not a physical description of what is going on internally at the
> register/stack level (which is always just shuffling values around -
> or flipping bits, as Steven points out), it is a higher level concept
> that helps people understand the *intention* (not necessarily the
> implementation) of the mechanism.

Right. And you can easily tell the difference, by whether an
assignment to the formal parameter causes any change to the actual
parameter that was passed in. If it does, that's call-by-reference.
If it doesn't, it's call-by-value. In Python, it doesn't. In VB.NET
(and relatives), it doesn't if the parameter is declared (explicitly
or implicitly) "ByVal", and does if it's declared "ByRef". (Whether
the parameter is a reference type or a simple value type makes no
difference.)

Python's behavior is exactly and always equivalent to the "ByVal"
behavior of languages that have both behaviors. It also matches the
definition of call-by-value. I quite agree that it's not helpful to
delve into the physical flipping of transistor states. We're talking
about the behavior, and the behavior, very clearly, is call-by-value.
To call it something else only clouds the issue and results in
confusion. (Perhaps explaining why there appears to be far more
confusion about call semantics in the Python community than in the
community of other languages where the default semantics are exactly
the same.)

Best,
- Joe


Dale Roberts

unread,
Oct 30, 2008, 3:06:39 PM10/30/08
to
On Oct 30, 11:03 am, Joe Strout <j...@strout.net> wrote:
> ...

>> Are you saying that C++ is capable of using the Call By Reference idiom,
>> but C is not, because C does not have a reference designation for formal
>> function parameters?
>
> It's been a LONG time since I did anything in C, but yes, I believe  
> that reference parameters were an addition that came with C++.

Okay, I completely understand you, and I think we will just have to
agree to disagree about the best term to use for Python's parameter
passing mechanism, and this will likely be my concluding post on this
topic (although I have enjoyed it very much and have solidified my own
understanding).

I even found a few web sites that very strongly support your viewpoint
(as it relates to Java):

http://www.ibm.com/developerworks/library/j-praxis/pr1.html
http://javadude.com/articles/passbyvalue.htm
http://www.yoda.arachsys.com/java/passing.html

The difference is that I would say that C supports the Pass By
Reference idiom using this syntax:

myfunc(int *val){} /*CALL:*/ myfunc(&i);

which actually passes an address expression (not a variable) by value,
but "looks and feels" like a reference to the "i" variable, which
contains the real value that we care about - and allows modification
of that value.

C++ adds a syntactic change for this very commonly used C idiom, but
does not add any new capability - the results are absolutely
indistinguishable.

Python, likewise, in relation to the values we care about (the values
contained only in objects, never in variables) behaves like Call by
Object Reference.

If I tell someone that Python uses only Call By Value (and that is all
I tell them), they may come away with the impression that variables
contain the values they care about, and/or that the contents of
objects are copied, neither of which is the case, even for so-called
"simple", immutable objects (indeed, at the start of this thread, you
said you believed that, like Java, simple values were contained within
Python variables).

But Python, unlike Java or most other commonly used languages, can
ONLY EVER pass an object reference, and never an actual value I care
about, and I think that idiom deserves a different name which
distinguishes it from the commonly accepted notion of Pass By Value.

Thanks for a thoughtful discussion,
dale

Dale Roberts

unread,
Oct 30, 2008, 4:41:40 PM10/30/08
to
On Oct 30, 3:06 pm, Dale Roberts <goobe...@gmail.com> wrote:
> ... that idiom deserves a different name which

> distinguishes it from the commonly accepted notion of Pass By Value.

Bah, what I meant to end with was:

Just as the Pass By Reference idiom deserves a unique name to
distinguish it from Pass By Value (even though it is often Pass By
(address) Value internally), so Pass By Object Reference deserves a
unique name (even though it too is Pass By (reference) Value
internally).

Again, thanks for the discussion,
dale

greg

unread,
Oct 30, 2008, 8:38:23 PM10/30/08
to
Douglas Alan wrote:
> greg <gr...@cosc.canterbury.ac.nz> writes:
>
>>Seems to me that (1) describes exactly how parameter passing
>>works in Python. So why insist that it's *not* call by value?
>
> Because there's an important distinction to be made,

The distinction isn't about parameter passing, though, it's
about the semantics of *assignment*. Once you understand
how assigment works in Python, all you need to know then
is that parameters are passed by assigning the actual
parameter to the formal parameter. All else follows from
that.

This holds for *all* languages that I know about, both
static and dynamic. Once you know how assignment works in
the language concerned, then you know how parameter
passing works as well. There is no need for new terms.

> and the
> distinction has been written up in the Computer Science literature
> since Lisp first starting using the same argument passing semantics as
> Python back in 1958. The semantics are called "call by sharing".

I still think it's an unnecessary term, resulting from
confusion on the part of the authors about the meanings of
the existing terms.

If there's any need for a new term, it would be "assignment
by sharing". Although there's already a term in use for that,
too -- it's known as reference assignment.

> Many mainstream programming languages other than Python now use call
> by sharing. They include Java, JavaScript, Ruby, ActionScript, and C#.

I would say they use assignment by sharing, and call by
value.

--
Greg

greg

unread,
Oct 30, 2008, 8:44:48 PM10/30/08
to
Gabriel Genellina wrote:
> En Tue, 28 Oct 2008 00:58:10 -0200, greg <gr...@cosc.canterbury.ac.nz>
> escribió:
>
>> (1) Call by value: The actual parameter is an expression. It is
>> evaluated and the result is assigned to the formal parameter.
>> Subsequent assignments to the formal parameter do not affect
>> the actual parameter.
>>
>> (2) Call by reference: The actual parameter is an lvalue. The
>> formal parameter becomes an alias for the actual parameter,
>> so that assigning to the formal parameter has the same
>> effect as assigning to the actual parameter.
>
> Those definitions are only applicable to unstructured, primitive types,
> where the only relevant operations are "get value" and "assign value".
> Structured types provide other operations too - like selection
> (attribute get/set in Python).

But that isn't what "assigning to the formal parameter" means --
it only means assigning directly to the parameter *name*.

> It is unspecified on both definitions
> above what happens in those cases.

That's true, but it's outside the scope of the parameter passing
mechanism to define what happens in those cases. That's down to
the data model being used by the language and the semantics of
assignment in general.

--
Greg

greg

unread,
Oct 30, 2008, 8:58:13 PM10/30/08
to
Dale Roberts wrote:

> Okay, you can have it that way, but every time you explain to someone
> that Python passes "By Value", you will have to add the additional
> baggage that, oh, by the way, there is a completely different meaning
> for "value" in Python than what you are used to.

For what it's worth, I happen to agree that telling
someone that Python passes parameters "by value" without
being sure they understand exactly what "by value"
means, is not a good idea -- not because the term
isn't well-defined, but because of the widespread
confusion out there about it.

But equally I wouldn't tell someone that it's *not*
by value, because if they do happen to correctly
understand what it means, that will confuse them just
as much.

So my recommendation is just to tell them that it
works by assigning the result of evaluating the actual


parameter to the formal parameter.

If they understand how assignment works in Python, that
tells them all they need to know.

If they don't understand how assignment works, then they
have a more fundamental knowledge gap that needs to be
corrected first.

--
Greg

Steven D'Aprano

unread,
Oct 30, 2008, 9:56:11 PM10/30/08
to
On Thu, 30 Oct 2008 09:03:42 -0600, Joe Strout wrote:

> Python's behavior is exactly and always equivalent to the "ByVal"
> behavior of languages that have both behaviors.

Pascal has both ByVal and By Ref, and Python's behaviour is absolutely
not the same as Pascal's ByVal.

> It also matches the definition of call-by-value.

Which definition of call-by-value? Certainly not the one that most people
are familiar with, where c-b-v implies that calling a function with a
large array will copy the entire array.


> I quite agree that it's not helpful to
> delve into the physical flipping of transistor states.

Nor is it helpful to delve into the implementation details of pointers
and references. There are no such things in Python code, and the Python
virtual machine doesn't see them. Only the underlying implementation sees
them, and as Fuzzyman has already explained, the .Net implementation of
IronPython differs from the C implementation of CPython, and this has
real consequences for Python code exposed to .Net objects.


> We're talking
> about the behavior, and the behavior, very clearly, is call-by-value.

Only if you redefine c-b-v to something that it unrecognizable to anyone
else.

Joe, you've got a cheek sneering at us for inventing new terms (that we
didn't in fact invent, that have a long history in the IT field, one
involving such giants as Barbara Liskov) when your entire argument rests
on the hijacking of the word "value" to mean "some arbitrary,
implementation-dependent reference to the thing which is the actual
value".

It is an abuse of language and common sense to claim that after executing
x=42, the "value" of x is 149605700 (or whatever arbitrary memory
location you happen to get). That nonsensical idea is the bedrock of your
entire argument.

--
Steven

Steven D'Aprano

unread,
Oct 30, 2008, 10:05:45 PM10/30/08
to
On Fri, 31 Oct 2008 13:58:13 +1300, greg wrote:

> Dale Roberts wrote:
>
>> Okay, you can have it that way, but every time you explain to someone
>> that Python passes "By Value", you will have to add the additional
>> baggage that, oh, by the way, there is a completely different meaning
>> for "value" in Python than what you are used to.
>
> For what it's worth, I happen to agree that telling someone that Python
> passes parameters "by value" without being sure they understand exactly
> what "by value" means,

"By value" is very simple. It means a copy of the value is passed to the
function.

Using "call by value" to mean "pass a copy of a reference to the value"
is an abuse of terminology, because that's exactly what happens in call
by reference: a copy of the reference to the value is passed.


> is not a good idea -- not because the term isn't
> well-defined, but because of the widespread confusion out there about
> it.

Well duh. All these people trying to insist that after executing x=1 the
value of x is some arbitrary memory location are certainly confused.


> But equally I wouldn't tell someone that it's *not* by value, because if
> they do happen to correctly understand what it means, that will confuse
> them just as much.

But it isn't call by value. Why wouldn't you tell people it is when the
value isn't being copied?

> So my recommendation is just to tell them that it works by assigning the
> result of evaluating the actual parameter to the formal parameter.

And 99% of them will just say "What?".

That's not an explanation, it's obfuscation at its worst. What *is* the
result of evaluating the actual parameter? Is it a reference to the
object or the object itself? Is it a copy of the object? A shallow copy?
A deep copy? Not a copy at all? What implications for behaviour does it
have? What does it mean?

> If they understand how assignment works in Python, that tells them all
> they need to know.

Nonsense.


--
Steven

Aaron Brady

unread,
Oct 30, 2008, 10:55:57 PM10/30/08
to
On Oct 30, 9:05 pm, Steven D'Aprano <st...@REMOVE-THIS-

cybersource.com.au> wrote:
> On Fri, 31 Oct 2008 13:58:13 +1300, greg wrote:
> > Dale Roberts wrote:
>
snip

>
> > If they understand how assignment works in Python, that tells them all
> > they need to know.
>
> Nonsense.

Maybe I missed this part. What does the phrase, "value of variable x"
mean in Python? Is it the same as what it means in C, Pascal, etc.?

In other words,

>>> x= [ 2, 3, 4 ]
>>> '0x%x'%id( x )
'0xb39dd0'

What is the value of 'x'?
a) [ 2, 3, 4 ]
b) An object with contents [ 2, 3, 4 ]
c) 0xb39dd0
d) None of the above.

I hold that the burden of proof is yours if you hold that there is
more than one answer.

If "value of 'x'" is not defined, we should agree on a definition
that's really clear and useful, favoring useful. After that's
established, we can proceed to evaluating what 'call by value' would
behave like, which would then determine if Python behaves like it.

So, logically, if... she... weighs... the same as a duck,... she's
made of wood.

Joe Strout

unread,
Oct 30, 2008, 11:07:03 PM10/30/08
to Python List
On Oct 30, 2008, at 6:38 PM, greg wrote:

> The distinction isn't about parameter passing, though, it's
> about the semantics of *assignment*. Once you understand
> how assigment works in Python, all you need to know then
> is that parameters are passed by assigning the actual
> parameter to the formal parameter. All else follows from
> that.
>
> This holds for *all* languages that I know about, both
> static and dynamic.

Just to be complete, it only holds in "ByVal" mode (for languages that
have both ByVal and ByRef modes, like VB.NET). A call-by-value
parameter pass is equivalent to an assignment to the formal parameter,
as you say. A call-by-reference parameter is not.

This is yet another simple way to see what type of parameter passing
Python uses.

> Once you know how assignment works in
> the language concerned, then you know how parameter
> passing works as well. There is no need for new terms.

Agreed.

Best,
- Joe


Joe Strout

unread,
Oct 30, 2008, 11:07:08 PM10/30/08
to Python List
On Oct 30, 2008, at 6:58 PM, greg wrote:

> For what it's worth, I happen to agree that telling
> someone that Python passes parameters "by value" without
> being sure they understand exactly what "by value"
> means, is not a good idea -- not because the term
> isn't well-defined, but because of the widespread
> confusion out there about it.
>
> But equally I wouldn't tell someone that it's *not*
> by value, because if they do happen to correctly
> understand what it means, that will confuse them just
> as much.
>
> So my recommendation is just to tell them that it
> works by assigning the result of evaluating the actual
> parameter to the formal parameter.
>
> If they understand how assignment works in Python, that
> tells them all they need to know.
>
> If they don't understand how assignment works, then they
> have a more fundamental knowledge gap that needs to be
> corrected first.

That's a very sensible stance. +1!

Best,
- Joe


Douglas Alan

unread,
Oct 30, 2008, 11:14:22 PM10/30/08
to
greg <gr...@cosc.canterbury.ac.nz> writes:

> Douglas Alan wrote:
>> greg <gr...@cosc.canterbury.ac.nz> writes:
>>
>>>Seems to me that (1) describes exactly how parameter passing
>>>works in Python. So why insist that it's *not* call by value?
>> Because there's an important distinction to be made,
>
> The distinction isn't about parameter passing, though, it's about
> the semantics of *assignment*. Once you understand how assigment
> works in Python, all you need to know then is that parameters are
> passed by assigning the actual parameter to the formal
> parameter. All else follows from that.
>
> This holds for *all* languages that I know about, both
> static and dynamic.

Then you don't know about all that many languages. There are
languages that use call-by-name, and those that use
call-by-value-return. Some use call-by-need and others do
call-by-macro-expansion. Etc. These languages generally don't use
these same semantics for assignment.

All languages that I know of that use call-by-sharing also do
assignment-by-sharing. Not all languages that do
assignment-by-sharing always do only call-by-sharing, however. For
instance, most dialects of Lisp have procedural macros. The calling
semantics of procedural macros are quite different from the calling
semantics of normal functions, even though procedural macros are Lisp
functions. Other dialects of Lisp provide the ability to state that
certain function arguments won't be evaluated at call time. All
dialects of Lisp, however, do assignment-by-sharing, or "binding" as
it is called in the Lisp community.

Also, one could certainly invent additional languages that do behave
in the typical manners.

If you are merely asserting, however, that understanding how Python
does assignment will help you understand how Python does argument
passing, then you are certainly correct. This, however, does not
imply that there is not a pre-existing precise terminology to describe
Python's calling semantics, and that this term can be useful in
describing how Python works.

If I tell you, for instance, that Java, Python, Ruby, JavaScript,
Lisp, and CLU all use call-by-sharing, then I have said something that
makes a similarity among these languages easier to state and easier to
grasp.

> Once you know how assignment works in the language concerned, then
> you know how parameter passing works as well. There is no need for
> new terms.

This is simply not true.

>> and the distinction has been written up in the Computer Science
>> literature since Lisp first starting using the same argument
>> passing semantics as Python back in 1958. The semantics are called
>> "call by sharing".
>
> I still think it's an unnecessary term, resulting from confusion on
> the part of the authors about the meanings of the existing terms.

Trust me, Barbara Liskov was not one bit confused when she invented
the term "call-by-sharing". And her language CLU was one of the most
prescient to have ever been designed and implmented.

> If there's any need for a new term, it would be "assignment by
> sharing". Although there's already a term in use for that, too --
> it's known as reference assignment.

Reference assignement doesn't imply that the object is allocated on a
heap, and "call-by-sharing" does.

>> Many mainstream programming languages other than Python now use call
>> by sharing. They include Java, JavaScript, Ruby, ActionScript, and C#.
>
> I would say they use assignment by sharing, and call by value.

We can also argue about how many angels can dance on the head of a
pin, but the term "call-by-sharing" has been around since the 70s, and
it is already well-defined and well understood.

|>oug

greg

unread,
Oct 31, 2008, 2:27:19 AM10/31/08
to
Dale Roberts wrote:
> Are you
> saying that C++ is capable of using the Call By Reference idiom, but C
> is not, because C does not have a reference designation for formal
> function parameters?

Call by reference is not an "idiom", it's a *language
feature*.

Pascal has it (using "var"), VB.NET has it (using "ByRef"),
C++ has it (using "&"). C does not have it, because there is
no syntax in the language for it. Neither does Python.

You can use an idiom in C to get the same effect, but this
is not the same thing as the language having it as a feature.

> You cannot look a C++ programmer straight in the eye and say that
> "Python uses Call By Value, Period", without also informing them that
> "Python variables can ONLY EVER hold object references - that is the
> only "value" they can ever hold".

But he had darn well better learn that anyway, otherwise he's
going to have massive problems programming in Python that
don't have anything to do with parameter passing!

--
Greg

greg

unread,
Oct 31, 2008, 3:07:16 AM10/31/08
to
Joe Strout wrote:

> (Perhaps explaining why there appears to be far more
> confusion about call semantics in the Python community than in the
> community of other languages where the default semantics are exactly
> the same.)

I think part of the problem stems from the fact that the
word "value" is often used rather loosely in relation to
Python, sometimes to mean a reference to an object and
sometimes to the contents of the object itself. So there's
a tendency to avoid using it when trying to speak
precisely. Some even go so far as to declare that there is
no such thing as a "value" in Python.

Then people see the term "call by value", and have a
fit of apoplexy because it has the forbidden word "value"
in it. How can we apply this term, they say, if we can't
decide what a value is?

The way out is to realise that you don't *have* to assign
any meaning to the term "value" in order to apply the
term "call by value".

If you look at the definitions I posted, you'll notice that
I carefully avoided using the terms "value", "reference",
"variable", "address" or any other such controversial words.

I did use the notion of the "result of evaluating an
expression", but only in the context of assigning it to a
name. Nobody seems to have any qualms talking about that in
Python, as far as I know.

So in summary, just treat the terms "call by value" and
"call by reference" as atomic identifiers, defined in terms
of assignment semantics. Don't try to pick them apart and
understand them in terms of "values" and "references".

--
Greg

greg

unread,
Oct 31, 2008, 3:15:30 AM10/31/08
to
Dale Roberts wrote:

> Just as the Pass By Reference idiom deserves a unique name to
> distinguish it from Pass By Value (even though it is often Pass By
> (address) Value internally), so Pass By Object Reference deserves a
> unique name (even though it too is Pass By (reference) Value
> internally).

Since Python only has one parameter passing mechanism,
there's no need to give it a name at all. If you're
having to explain it, just explain it, and don't
bother naming it!

--
Greg

greg

unread,
Oct 31, 2008, 3:22:23 AM10/31/08
to
Steven D'Aprano wrote:

> Which definition of call-by-value? Certainly not the one that most people
> are familiar with, where c-b-v implies that calling a function with a
> large array will copy the entire array.

But that's only true in languages where *assigning* a large
array will also copy the entire array. This does not happen
in Python, therefore there is no reason to suppose that it
will happen when passed as a parameter.

Before you can understand parameter passing, whether by-value
or by-reference, you first have to understand how assignment
works *in the language concerned*, not some other language
you happen to know previously.

--
Greg

greg

unread,
Oct 31, 2008, 3:41:27 AM10/31/08
to
Steven D'Aprano wrote:

> "By value" is very simple. It means a copy of the value is passed to the
> function.

It only means that if you understand "copy" to mean
whatever it is that happens when you perform an assignment.
In Python, the term "copy" tends to imply rather more
than that, so you go off the rails using that definition.

>> So my recommendation is just to tell them that it works by assigning the
>> result of evaluating the actual parameter to the formal parameter.

> That's not an explanation, it's obfuscation at its worst.

I didn't necessarily mean to use those exact words. The
essential point is that you explain parameter passing in
terms of assignment.

> What *is* the
> result of evaluating the actual parameter? Is it a reference to the
> object or the object itself?

It doesn't matter! All that matters is that they understand
what happens when you assign it to a name. You can explain
that using whatever terminology you want, as long as they
end up with a mental model that works. Then you tell them
that passing a parameter is just like doing an assignment.

I can't think what could be simpler or less obfuscatory
than that.

>>If they understand how assignment works in Python, that tells them all
>>they need to know.
>
> Nonsense.

Why? What else *do* you think they need to know?

--
Greg

greg

unread,
Oct 31, 2008, 3:47:44 AM10/31/08
to
Aaron Brady wrote:

> Maybe I missed this part. What does the phrase, "value of variable x"
> mean in Python?

I didn't use the phrase "value of variable x" anywhere in my
definitions, so it doesn't matter what it means, or even
whether it means anything at all.

> If "value of 'x'" is not defined, we should agree on a definition
> that's really clear and useful, favoring useful. After that's
> established, we can proceed to evaluating what 'call by value' would
> behave like, which would then determine if Python behaves like it.

There you go, getting distracted by that annoying word
"value". Forget about it, we don't need it!

--
Greg

Message has been deleted

greg

unread,
Oct 31, 2008, 4:03:15 AM10/31/08
to
Douglas Alan wrote:
> greg <gr...@cosc.canterbury.ac.nz> writes:

>>This holds for *all* languages that I know about, both
>>static and dynamic.
>
> Then you don't know about all that many languages. There are
> languages that use call-by-name, and those that use
> call-by-value-return. Some use call-by-need and others do
> call-by-macro-expansion. Etc.

I didn't mean that these are the only two parameter passing
mechanisms in existence -- I know there are others.

What I mean is that in all languages I know of that have
by-value or by-reference or both, they behave according to
the definitions I gave. If anyone has a counterexample,
I'll be interested to hear about it.

> For
> instance, most dialects of Lisp have procedural macros. The calling
> semantics of procedural macros are quite different from the calling
> semantics of normal functions

Yes, but nobody refers to that as either by-value or
by-reference as far as I know. Lisp people would probably
talk about the parameter being passed either "evaluated"
or "unevaluated".

> If I tell you, for instance, that Java, Python, Ruby, JavaScript,
> Lisp, and CLU all use call-by-sharing, then I have said something that
> makes a similarity among these languages easier to state and easier to
> grasp.

If you told me they use "assignment by sharing", that would tell me
a lot *more* about the language than just talking about parameter
passing.

--
Greg

greg

unread,
Oct 31, 2008, 4:11:27 AM10/31/08
to
Steven D'Aprano wrote:

> Using "call by value" to mean "pass a copy of a reference to the value"
> is an abuse of terminology, because that's exactly what happens in call
> by reference: a copy of the reference to the value is passed.

No, it's not a reference to a value, it's a reference to
a *variable* (what C calls an lvalue). There is no such
thing as a reference to an lvalue in Python.

The presence of the word "reference" in "call by
reference" is another nasty terminology collision,
because it has nothing to do with what's called a
"reference" in Python.

The historical choice of terms is somewhat unfortunate.
If they'd been called something like "call by assignment"
and "call by alias", none of this confusion would have
arisen.

--
Greg

Steven D'Aprano

unread,
Oct 31, 2008, 4:11:45 AM10/31/08
to
On Fri, 31 Oct 2008 20:07:16 +1300, greg wrote:

> Joe Strout wrote:
>
>> (Perhaps explaining why there appears to be far more confusion about
>> call semantics in the Python community than in the community of other
>> languages where the default semantics are exactly the same.)
>
> I think part of the problem stems from the fact that the word "value" is
> often used rather loosely in relation to Python, sometimes to mean a
> reference to an object and sometimes to the contents of the object
> itself. So there's a tendency to avoid using it when trying to speak
> precisely. Some even go so far as to declare that there is no such thing
> as a "value" in Python.

I think you're imagining that.

Perhaps you are confused by the fact that there are people (including
myself) who try to avoid using the term "assign to a variable" and prefer
to use "bind to a name" instead. But value? Given x=1, what else could
the value of x be other than the object 1?


> Then people see the term "call by value", and have a fit of apoplexy
> because it has the forbidden word "value" in it. How can we apply this
> term, they say, if we can't decide what a value is?

We know what a value is. A value is the thing denoted by a symbol. In the
context of Python, the value of the name x is the object bound to that
name.


> The way out is to realise that you don't *have* to assign any meaning to
> the term "value" in order to apply the term "call by value".

Call by value already has at least one well-established meaning. It's a
meaning that isn't compatible with what Python does.

In such languages as Pascal and C, a variable such as x refers to a fixed
memory location of a known size. The assignment x = 1 sets the bytes at
that location to the value 1. When you call func(x) the value of x (the
value 1) is copied to another memory location which is local to the
function.

The same holds when x is an array. If x is an array of 1MB, then func(x)
will copy 1MB of bytes into a local variable of func.

[...]


> So in summary, just treat the terms "call by value" and "call by
> reference" as atomic identifiers, defined in terms of assignment
> semantics. Don't try to pick them apart and understand them in terms of
> "values" and "references".


In other words, in order for "call by value" to have any meaning in
Python, we have to forget all about the ordinary meaning of the words
"value" and "references" and just treat them as magic words unrelated to
"call by value" in any other language.

Might as well call it "call by milk" or "call by fjH?agx" instead.


--
Steven

Steven D'Aprano

unread,
Oct 31, 2008, 4:18:18 AM10/31/08
to

This would make sense if Python was the only computer language in
existence, but it isn't. Consequently people who know these other
languages come along and ask "So is Python call by value or call by
reference?".

The correct answer to that is "No", but unfortunately there are far too
many people who refuse to accept the existence of any third parameter
passing mechanism and therefore confuse the issue by hammering the round
peg of Python's calling mechanism into the square hole of their pre-
conceptions. Depending on those particular pre-conceptions, they will
insist that Python "clearly and obviously is call by reference", or that
it is "clearly and obviously call by value, where the values are
references".


--
Steven

Bruno Desthuilliers

unread,
Oct 31, 2008, 5:00:56 AM10/31/08
to
greg a écrit :

Err... So what does "call by value" means if "values" doesn't mean
anything ?-)

Steven D'Aprano

unread,
Oct 31, 2008, 5:12:31 AM10/31/08
to
On Fri, 31 Oct 2008 20:22:23 +1300, greg wrote:

> Steven D'Aprano wrote:
>
>> Which definition of call-by-value? Certainly not the one that most
>> people are familiar with, where c-b-v implies that calling a function
>> with a large array will copy the entire array.
>
> But that's only true in languages where *assigning* a large array will
> also copy the entire array.

Maybe, maybe not. To be consistent, it should be true. But how do you
know if a language you are unfamiliar with is consistent?

In any case, to somebody only familiar with the classical value-vs-
reference model, Python seems rather inconsistent:


x = 1
y = x # does assignment make copies?
y += 1
assert x == 1
=> succeeds, which implies that Python makes a copy when assigning

x = [1]
y = x # does assignment make copies?
y += [1]
assert x == [1]
=> fails, which implies that Python uses references when assigning

Hence you get people who argue that Python does call-by-value for numbers
and call-by-reference for lists -- and yes, I've seen people make that
exact argument.

The reality is that Python isn't inconsistent, it merely seems to be if
you assume it is some other language. Python actually treats numbers and
lists identically.

When people discover that Python's behaviour doesn't fall neatly into
their preconceived notions of c-b-v and c-b-r, there are two ways of
dealing with that:

(1) Accept that perhaps there's at least one more way of doing assignment
and parameter passing.

(2) Or jump through hoops trying to force how Python works to somehow
match your preconceptions.

> This does not happen in Python, therefore
> there is no reason to suppose that it will happen when passed as a
> parameter.

Of course there is a reason: we've been told that Python is call by
value, and call by value implies that a copy is made when you pass it to
a function. The fact that many programmers already have an idea of what
they think c-b-v implies is what makes calling Python c-b-v such a
pernicious mistake. If you want to call Python "call by ginger" I won't
object, because most people have no preconceived ideas of what call by
ginger means and therefore won't be lured into incorrect assumptions
about Python.


> Before you can understand parameter passing, whether by-value or
> by-reference, you first have to understand how assignment works *in the
> language concerned*, not some other language you happen to know
> previously.

It's certainly true that the baggage people bring from their previous
languages can sometimes be a serious barrier, but that especially happens
when folk insist on using the same terminology to describe different
things.

For example, to somebody coming to Python from Lisp or Scheme, the word
"list" carries particular connotations. It's unfortunate that Python
lists are not like Lisp lists, but we're stuck with that now, and besides
there's only so many good names for a list-like array, and whatever name
was chosen would trip up somebody. Another example, augmented assignment
in Python trips up C programmers, because x += y looks the same but
behaves differently than x += y in C.

There's enough difficulty with learning a new programming language
without people adding to it by misusing terms like "call by value" to
describe what Python does.


--
Steven

Steven D'Aprano

unread,
Oct 31, 2008, 5:23:27 AM10/31/08
to
On Thu, 30 Oct 2008 19:55:57 -0700, Aaron Brady wrote:

> On Oct 30, 9:05 pm, Steven D'Aprano <st...@REMOVE-THIS-
> cybersource.com.au> wrote:
>> On Fri, 31 Oct 2008 13:58:13 +1300, greg wrote:
>> > Dale Roberts wrote:
>>
> snip
>>
>> > If they understand how assignment works in Python, that tells them
>> > all they need to know.
>>
>> Nonsense.
>
> Maybe I missed this part. What does the phrase, "value of variable x"
> mean in Python? Is it the same as what it means in C, Pascal, etc.?
>
> In other words,
>
>>>> x= [ 2, 3, 4 ]
>>>> '0x%x'%id( x )
> '0xb39dd0'
>
> What is the value of 'x'?
> a) [ 2, 3, 4 ]
> b) An object with contents [ 2, 3, 4 ]
> c) 0xb39dd0
> d) None of the above.

Solution a) is just shorthand for b), because there are (or at least
could be) many such objects [2, 3, 4]. So I'd accept either a) or b) as
reasonable answers.

Solution c) is the answer that is required for "Python is call-by-value"
to be correct.


> If "value of 'x'" is not defined, we should agree on a definition that's
> really clear and useful, favoring useful.

The ordinary dictionary meaning is sufficient: "what is denoted by a
symbol".


> After that's established, we
> can proceed to evaluating what 'call by value' would behave like, which
> would then determine if Python behaves like it.

Call by value is traditionally defined in at least some languages as
meaning that a copy of the value of the parameter is passed to the
function. Those languages include C and Pascal, and possibly Basic. I'd
estimate that 80% of programmers over the last 40 years have had their
understanding of "call by whatever" shaped by those three languages.


> So, logically, if... she... weighs... the same as a duck,... she's made
> of wood.

Nice one :)


--
Steven

Arnaud Delobelle

unread,
Oct 31, 2008, 5:29:49 AM10/31/08
to
On Oct 31, 9:12 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
[...]

> There's enough difficulty with learning a new programming language
> without people adding to it by misusing terms like "call by value" to
> describe what Python does.

Maybe it could be named 'call by assignment'?

Then the focus might shift towards misconceptions about assignment and
augmented assignment, which are more often than not at the root of
people's misunderstandings.

--
Arnaud

Grant Edwards

unread,
Oct 31, 2008, 9:59:46 AM10/31/08
to

Unfortunately, that's not really how the human mind works. It
likes to have names for things and put them in categories of
like things. Hence the large collection of nouns in all human
languages.

--
Grant Edwards grante Yow! Th' MIND is the Pizza
at Palace of th' SOUL
visi.com

Dale Roberts

unread,
Oct 31, 2008, 10:03:52 AM10/31/08
to

But then why bother having any other names at all for other languages
that have only one calling mechanism, like Call By Name, Call By Macro
Expansion, etc.

If it is a different process, it needs a different name. OR, as you
suggest, no name at all, just an explanation.

But please don't give it the WRONG name!

Dale Roberts

unread,
Oct 31, 2008, 10:35:19 AM10/31/08
to
On Oct 31, 2:27 am, greg <g...@cosc.canterbury.ac.nz> wrote:
> Dale Roberts wrote:
> > Are you
> > saying that C++ is capable of using the Call By Reference idiom, but C
> > is not, because C does not have a reference designation for formal
> > function parameters?
>
> Call by reference is not an "idiom", it's a *language
> feature*.
> ...

> You can use an idiom in C to get the same effect, but this
> is not the same thing as the language having it as a feature.

Okay, I'll grant that, but is there a language other than Python that
uses the Call By Value feature that does not do it by assigning/
copying the result of an expression into the formal parameter?

The terms "result" and "value" are generally understood to refer to
the working data of the program, not the internal workings of the
interpreter, VM, or compiler.

So, yes, internally the C Python runtime does use Call By Value. It's
written in C after all - that's all it can do.

But Call By Value is not a feature of the Python language.

dale

[Somebody unplug my network cable! I can't stop!]

pjaco...@googlemail.com

unread,
Oct 31, 2008, 11:42:53 AM10/31/08
to
Instead of comparing integers:

> x = 1
> y = x # does assignment make copies?
> y += 1
> assert x == 1
> => succeeds, which implies that Python makes a copy when assigning

with lists:

> x = [1]
> y = x # does assignment make copies?
> y += [1]
> assert x == [1]
> => fails, which implies that Python uses references when assigning

Compare lists with tupels:

x = (1,)


y = x # does assignment make copies?

y += (1,)
assert x == (1,)
=> succeeds, which implies *what*?

Regards,
Peter

Duncan Booth

unread,
Oct 31, 2008, 12:02:53 PM10/31/08
to
pjaco...@googlemail.com wrote:

All any of this does is 'implies that += may create a new object or may
mutate an existing object. RTFM: Python Reference Manual 6.3.1

"An augmented assignment expression like x += 1 can be rewritten as x = x +
1 to achieve a similar, but not exactly equal effect. In the augmented
version, x is only evaluated once. Also, when possible, the actual
operation is performed in-place, meaning that rather than creating a new
object and assigning that to the target, the old object is modified
instead."

--
Duncan Booth http://kupuguy.blogspot.com

Douglas Alan

unread,
Oct 31, 2008, 12:37:57 PM10/31/08
to
greg <gr...@cosc.canterbury.ac.nz> writes:

> Douglas Alan wrote:
>> greg <gr...@cosc.canterbury.ac.nz> writes:
>
>>> This holds for *all* languages that I know about, both static and
>>> dynamic.
>
>> Then you don't know about all that many languages. There are
>> languages that use call-by-name, and those that use
>> call-by-value-return. Some use call-by-need and others do
>> call-by-macro-expansion. Etc.
>
> I didn't mean that these are the only two parameter passing
> mechanisms in existence -- I know there are others.

I don't follow you. You stated that once you understand how
assignment works, you understand the calling mechanism. That's just
not true. Algol, for instance, did assignment-by-value but
call-by-name.

>> If I tell you, for instance, that Java, Python, Ruby, JavaScript,
>> Lisp, and CLU all use call-by-sharing, then I have said something that
>> makes a similarity among these languages easier to state and easier to
>> grasp.
>
> If you told me they use "assignment by sharing", that would tell me
> a lot *more* about the language than just talking about parameter
> passing.

Not really. Call-by-sharing virtually implies that the language does
assignment-by-sharing. (I know of no counter-examples, and it is
difficult to see how a violation of this rule-of-thumb would be useful
in any new language.) Stating that a language does
assignment-by-sharing does not imply that it does call-by-sharing. Or
at least not exclusively so. Cf. certain dialects of Lisp. Also C#,
which supports a variety of argument passing strategies.

|>oug

Steven D'Aprano

unread,
Oct 31, 2008, 8:05:12 PM10/31/08
to


To somebody who is stuck in the traditional mentality of "call by
reference" versus "call by value", it implies that Python copies tuples
and ints (and strings, and frozensets) but not lists (and dicts and sets
and class instances).

They would be wrong, but when you start with faulty assumptions that is
often the case. The assumption that there are only two calling
conventions is such a pernicious assumption. Look at how many thousands
of words have been spent trying to get Joe to understand that c-by-r and
c-b-v are not the only two options, and that what Python does is not
either c-b-r or c-b-v.


--
Steven

It is loading more messages.
0 new messages