Finding the instance reference of an object

A

Astley Le Jasper

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'
 
A

Astley Le Jasper

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

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.
 
S

Steven D'Aprano

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)
 
D

Diez B. Roggisch

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

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
 
L

Larry Bates

Astley said:
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
 
J

Joe Strout

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
 
A

Astley Le Jasper

Astley Le Jasper schrieb:


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.
 
A

Aaron \Castironpi\ Brady

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.
 
S

Steven D'Aprano

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".
 
S

Steven D'Aprano

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.
 
A

Aaron \Castironpi\ Brady

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.

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.
 
T

Terry Reedy

Astley said:
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]
...
 
L

Larry Bates

Joe said:
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.


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.)


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
 
J

Joe Strout

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.
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
 
J

Joe Strout

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.
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.
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.
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.)
But they don't...

They really, really do.
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!
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!
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
 
A

Aaron \Castironpi\ Brady

On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote: snip

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'.
 
J

Joe Strout

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
 
S

Steve Holden

Joe said:
On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote: [much blether]
As far as I'm concerned -- everything is "by ref" in Python...

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

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

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

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

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

In [10]: foo(a)

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

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

In [13]: ffoo(a)

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

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

In [16]: fffoo(a)

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

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

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

In the case of lists,

a = a + [something]

rebinds a, while

a += [something]

doesn't. So where does that leave you?
But if Python has any such feature, I'm not aware of it. Certainly the
default behavior is to pass everything (even object references) by
value. Assignments made to them don't affect anything else.
Mutation of an object is never a bare LHS... It is either a method
call of the name

alist.append()

or a drill-down going inside the object

alist[2] = something
anobject.attribute = something
adict["key"] = something

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

In [18]: a = 42

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

In [20]: a += 1

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

In [22]: a = []

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

In [24]: a += [42]

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

In other words, the behavior of augmented operations depends on whether
the reference is to a mutable or an immutable value.
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.
It might be simpler to say "Change this name to be a reference to that
value", or "Change this name to be a reference to the [result of
evaluating the] expression on the RHS".

Or indeed, "Change the content of that container element to be a
reference to the [result of evaluating the] expression on the RHS"
What does that mean, exactly? It means: "replace the contents (i.e.
object reference) of the memory location associated with this name with
the contents (i.e. object reference) of the memory to which that name
is associated by copying the contents from there to here."

It's the exact same thing. (And exactly the same as in any other
language.)
If you mean it's a reference assigment, of course it is. That's what he
was trying to say (I believe). But in C, for example,

int i;
i = 42;

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

int *i;
i = &42;

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

i = 42
They really, really do.


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.


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


Hey, I remember Pascal... that was the language used on the Apple IIGS,
back when I was in junior high. I also remember spending $800 for a
40MB hard drive for it. Ah, those were the days!
40 Mb! You were lucky! Etc., etc., [drools into beard.]
No, it suggests to me that there's a lot of confusion in the Python
community. :) It appears as though people either (a) really want to
think that Python's object handling is special and unique for emotional
reasons, or (b) are comparing it to really ancient languages that didn't
have any notion of objects and object references. This has led to
making up new terminology and spreading confusion. I'm coming back to
Python from almost a decade of working with other modern languages
(including implementing the compiler for one of them), and I don't see
any difference at all between Python's object handling and those.
Python's assignment semantics (as opposed to its "object handling, a
term for which I have no referent) are not the same as those of, say C.
I believe they are pretty much the same ass those of Icon, another
non-standard interpreted language.

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

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

regards
Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top