473,287 Members | 1,426 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

Finding the instance reference of an object

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'
Oct 16 '08 #1
275 11970
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 Haese
http://informixdb.sourceforge.net
Oct 16 '08 #2
On Oct 16, 4:01*pm, Astley Le Jasper <Astley.lejas...@gmail.com>
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'

This is a FAQ:

http://www.python.org/doc/faq/progra...e-of-an-object
Oct 16 '08 #3
On 16 Oct, 16:52, Carsten Haese <carsten.ha...@gmail.comwrote:
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.
Oct 16 '08 #4
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
Oct 16 '08 #5
Astley Le Jasper schrieb:
On 16 Oct, 16:52, Carsten Haese <carsten.ha...@gmail.comwrote:
>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.
Why not simply do

bob = someobject(0, 1, 2)

?

Diez
Oct 16 '08 #6
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'
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
Oct 16 '08 #7
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

Oct 16 '08 #8
On 16 Oct, 18:53, "Diez B. Roggisch" <de...@nospam.web.dewrote:
Astley Le Jasper schrieb:
On 16 Oct, 16:52, Carsten Haese <carsten.ha...@gmail.comwrote:
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.

Why not simply do

bob = someobject(0, 1, 2)

?

Diez
Because that was pseudo code to demonstrate what I was trying to
achieve. The parameters are more complicated than that.
Oct 16 '08 #9
Thanks for all the responses. That helps.

Ta

ALJ
Oct 16 '08 #10
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.
Oct 16 '08 #11
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
Oct 17 '08 #12
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
Oct 17 '08 #13
On Oct 16, 8:30*pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.auwrote:
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
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.
Oct 17 '08 #14
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]
...

Oct 17 '08 #15
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.
>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
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
Oct 17 '08 #16
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

Oct 17 '08 #17
On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <jo*@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
Oct 17 '08 #18
On Oct 17, 10:56*am, Joe Strout <j...@strout.netwrote:
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'.
Oct 17 '08 #19
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
Oct 17 '08 #20
On Oct 17, 4:03*pm, Joe Strout <j...@strout.netwrote:
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
Oct 17 '08 #21
On Oct 17, 5:19 pm, Grant Edwards <gra...@visi.comwrote:
On 2008-10-17, Joe Strout <j...@strout.netwrote:
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
Oct 17 '08 #22
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/...LCS-TR-225.pdf

quoted by Fredrik Lundh here:
http://mail.python.org/pipermail/pyt...ay/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
Oct 19 '08 #23
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 <jo*@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/pyt...ay/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/articl...tractions.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_...e-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
Oct 19 '08 #24
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 +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Oct 19 '08 #25
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 +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Oct 19 '08 #26
On Oct 17, 10:39*pm, Joe Strout <j...@strout.netwrote:
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/
Oct 22 '08 #27
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com.auwrites:
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
Oct 27 '08 #28
On Oct 17, 5:39*pm, Joe Strout <j...@strout.netwrote:
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
Oct 27 '08 #29
On Oct 17, 5:39 pm, Joe Strout <j...@strout.netwrote:
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:

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, 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
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
Oct 27 '08 #30
On Oct 27, 2008, at 12:19 PM, go******@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
Oct 27 '08 #31
go******@gmail.com wrote:
On Oct 17, 5:39 pm, Joe Strout <j...@strout.netwrote:
>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

Oct 27 '08 #32
On Mon, 27 Oct 2008 13:11:04 -0600, Joe Strout wrote:
On Oct 27, 2008, at 12:19 PM, go******@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
Oct 27 '08 #33
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
<As*************@gmail.comwrote:
On 16 Oct, 16:52, Carsten Haese <carsten.ha...@gmail.comwrote:
>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
Oct 27 '08 #34
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
Oct 28 '08 #35
[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, go******@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
Oct 28 '08 #36
greg <gr**@cosc.canterbury.ac.nzwrites:
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.)
Oct 28 '08 #37
En Tue, 28 Oct 2008 00:58:10 -0200, greg <gr**@cosc.canterbury.ac.nz>
escribió:
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?
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

Oct 28 '08 #38
En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <go******@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

Oct 28 '08 #39
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.nzescribió:
>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
Oct 28 '08 #40
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*
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

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
Oct 28 '08 #41
On Oct 28, 11:59*am, Joe Strout <j...@strout.netwrote:
...

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
Oct 28 '08 #42
On Oct 27, 2:11*pm, Joe Strout <j...@strout.netwrote:
On Oct 27, 2008, at 12:19 PM, goobe...@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.
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'?
Oct 28 '08 #43
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
Oct 28 '08 #44
On 2008-10-17, Joe Strout <jo*@strout.netwrote:
>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
Oct 29 '08 #45
On 2008-10-29, Antoon Pardon <ap*****@forel.vub.ac.bewrote:
On 2008-10-17, Joe Strout <jo*@strout.netwrote:
>>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.
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
Oct 29 '08 #46
On Oct 28, 11:59*am, Joe Strout <j...@strout.netwrote:
...

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)
Oct 29 '08 #47
On Wed, Oct 29, 2008 at 5:27 PM, Dale Roberts <go******@gmail.comwrote:
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.
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
Oct 29 '08 #48
On Oct 28, 3:59*pm, Joe Strout <j...@strout.netwrote:
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.nzescribió:
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.
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.

Michael Foord
--
http://www.ironpythoninaction.com/
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
Oct 29 '08 #49
On Wed, 29 Oct 2008 08:27:07 -0700, Dale Roberts wrote:
On Oct 28, 11:59Â*am, Joe Strout <j...@strout.netwrote:
>...

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
Oct 29 '08 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Liming | last post by:
Hello all, I have a custom class object with some prototype methods like setKeyDownEvent, etc. The problem is on my webpage, after I instantiate the class, I try to do .addEventLister() to a...
7
by: Brad Baker | last post by:
I am trying to programmatically set a placeholder control in csharp which is nested inside a repeater control between <ItemTemplateand </ItemTemplate> tags, however I am running into problems. I've...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.