anything like C++ references?

Bengt Richter bokr at oz.net
Mon Jul 14 00:46:41 CEST 2003


On Sun, 13 Jul 2003 16:11:37 +0100, Stephen Horne <intentionally at blank.co.uk> wrote:

>On 13 Jul 2003 10:37:01 -0400, aahz at pythoncraft.com (Aahz) wrote:
>
>>In article <iqm2hvs77lhe1m71v9b579070khbf0uv0a at 4ax.com>,
>>Stephen Horne  <intentionally at blank.co.uk> wrote:
>>>
>>>One of the few things I hate about Python is that mutable objects are
>>>implicitly shared using a reference system whereas immutable objects
>>>are not. 
>>
>>Well, that's incorrect.  *ALL* Python objects are implicitly shared with
>>bindings.  The difference is whether updating the value referenced by a
>>target requires *re*binding the target or simply updating an object.
>
>Fine - nit-pick.
Well, it *is* a (very) significant nit ;-)

>
>All you have proven is that it is the distinction between types that
>get re-bound and those that don't (rather than the use of references)
>that is unnecessarily confusing and error prone.
I suspect you are reading some Python statements as if they were C or C++.

Python name assignment does not do anything to an object. It just creates
an alias name for an object. It may reuse an existing name, but that only
changes the meaning of that name as an alias, it does not affect the object
that the name was previously an alias for.

You can of course have other assignment targets than plain names. In fact,
a "plain name" is just the simplest expression for an assignment target.
But whatever the target expression evaluates to, what gets put "there" is
a reference to an object, not an object itself.

The confusion, ISTM, is in what to think of as "there." "There" is definitely
not a memory space for a Python object representation or "value". 

The most accurate (UIAM) C concept would be a "there" of type PyObject* -- i.e.,
a pointer variable that points to the representation of some kind of Python object.

We don't have to know the implementation details to use the idea that the left hand
side of a Python assignment is an *expression* (even if a single name) that yields
a place to put a reference (effectively a pointer) to the object created by evaluating
the expression on the right hand side.

A C programmer will tend to think that a symbol on the left is a static expression
indicating a specific fixed memory space (static address or stack frame offset). But in Python
it is first of all a dynamic expression (though an unqualified target name can only have its "there"
be in the local or global namespace, and the choice between those is made statically
(at least w.r.t. a given level of compiling/exec-ing).

In C terms, the Python assignment target expression always evaluates to a place to put a pointer,
never a place to put object representation bits. Of course, "a place to put a pointer"
may be *inside* an object. And such inside places are identified by target expressions
such as x[2] or x.a or x[2]().b[3] etc. Even a bare name really does identify a place inside
an object -- i.e., inside the local or global dict associated with the context.

The "place" identified by x= after a global x declaration (or just in global scope) will be the
same place as globals()['x']= unless someone has subverted something. Either way, the binding
of the name to the object happens by evaluating to a "there" within the global dict object,
uniquely associated with the name ('x' here). Evaluated on the right hand side, that name will
produce the reference/pointer again for use in accessing the object or copying to another "there"
associated with perhaps some other name or a target within a composite object like a list or tuple,
or other namespace dict.

>
>The wart remains, even if my description was wrong. And even that is a
>dubious claim.
>
Every assignment is effectively stores a referential alias for an object,
whether associated with a name or not. This is by design, not a wart.

>A Python user is interested in how an object behaves - not how it is
>internally implemented in the interpreter. Immutable objects don't
when you say "immutable objects," are you really speaking of names
bound to immutable objects? I.e., the integer 123 is an immutable object
represented by the literal 123. You get an immutable object of the same value
from the expression int('123'). These are the int *objects* -- how does
"behave as references" apply to these actual "immutable objects"?
I.e., could you rewrite your sentence (that this is breaking in two)
to make it perhaps more understandable for me ?;-)

Names are not objects. Nor are left-hand-side assignment target expressions
in general, whether bare names or complicated.

ISTM what you are discussing is not about objects but about the way names work,
and ISTM you are thinking of names as if they were C++ variable references,
which they are not, and they couldn't be. For one thing, a C++ reference type
has to be initialized once to refer to a specific object. It can't be made to
refer to something else during the life of that scope. Pointers are a better
model, since you have to distinguish by expression syntax whether you mean
to assign a new pointer value or modify the thing pointed to. In python you
can only assign pointers, if you want to think in those terms. When you
modify a mutable, you are still assigning pointers into some part of the
mutable object representation. When you assign to a bare name, you are still assigning
a pointer into a place in some dictionary object (or workalike). If you
want to modify an object in the usual C sense, you can code it in C and provide a
python interface to your C-implemented object. When you pass arguments
to the various methods of your mutable, you will get pointers that you
can dereference and you can do what you want to your mutable's C data representation.
But when you pass the result back to the python world, it will have to be
as a standard object reference/pointer, and if you assign that, you will be
storing a pointer somewhere.

>behave as references - the internal use of references for immutable
>objects is basically a lazy copying optimisation and, apart from
>performace and a couple of other technicalities (e.g. the 'is'
>operator), has no relevance. Certainly it has no relevance to the
>point I was making.
>
The way it works is part of the semantics of the language, not just
an optimization issue.

Names aren't variables.

HTH ;-)

<disclaimer>I sometimes get things wrong. Corrections welcome.</disclaimer>

Regards,
Bengt Richter




More information about the Python-list mailing list