Finding the instance reference of an object

Dale Roberts gooberts at gmail.com
Tue Oct 28 12:56:05 EDT 2008


On Oct 28, 2:33 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
wrote:
> En Tue, 28 Oct 2008 01:16:04 -0200, Dale Roberts <goobe... at 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



More information about the Python-list mailing list