...so would aliases be a bad idea? (Re: references / aliases in Python)

Bengt Richter bokr at oz.net
Thu Jan 16 07:04:02 EST 2003


On 15 Jan 2003 16:25:54 -0800, jbperez808 at yahoo.com (Jonathan P.) wrote:

>> The Python philosophy regarding poiner types is simple: there aren't any.
>> Names are references to values. Attributes of objects are references to
>> values. Elements of dictionaries, lists and tuples are references to values.
>> Values do not have names, they are simply bound by assignment (to names,
>> attributes of objects, or elements of dictionaries, lists and tuples). Each
>> value (object) has an associated reference counter, incremented and
>> decremented automatically as references are created and destroyed. When an
>> object's reference count reaches zero it becomes a candidate for garbage
>> collection. Special features allow collection of "cyclic garbage" to handle
>> the cases where a set of objects refer only to each other.
>
>So if one allows 2 different names to bind to the exact same object,
>would that be a bad idea?  There are many situations where one
The question, especially following the quote above, makes me think you don't
yet understand how names and objects relate in Python. Multiple names are
often bound to the same object in Python, and it's not a bad idea, but doing
so doesn't give you extra handles for changing the contents of a memory location
by using the bare names on the left hand side of an '=' in an assignment.

In other words

    name = xxx

does _NOT_ put xxx value in a location labeled name. What it does is tack
a little cardboard name tag on a particular cork-surfaced bulletin board, and
it ties a thread through a little eyelet in the name tag with a knot, and then
unreels enough thread to reach the xxx object and ties the other end to that.

Suppose the cork-surfaced board is the bulletin board on the wall of your
modular room, and xxx is your favorite chair object. Now tack up another
tag with another name on it, and also tie a thread from it to your chair.
Now maybe one tag says 'Jons_chair' and the other says
'Recliner_chair_#123439847_bought_by_Jon_from_Acme_Furniture_Jan_10_2003'

Tacking up more tags on the bulletin board does not do anything to the chair.

Now if you decide the recliner is too soft, and you want to replace it with
a wooden chair, you might want to write

    Jons_chair = wooden_chair

The effect is not to move the recliner out, however. The effect is to go to
the bulletin board and find the Jons_chair tag and detach its connecting thread
from the recliner and attach it instead to the wooden_chair object (found by
following the thread from the "wooden_chair" name tag on the bulletin board).

Now there's still two tags on the bulletin board, but the
'Recliner_chair_#123439847_bought_by_Jon_from_Acme_Furniture_Jan_10_2003' is
still connected by its thread to the old recliner. Changing the connection for
the Jons_chair alias tag didn't affect the big-name tag.

However, if you had added a pillow to the recliner instead, both name tag threads
would lead to a recliner with a pillow.

Now how did we find the actual wooden chair when we wrote

    Jons_chair = wooden_chair

? Well, wooden_chair in the source code is a name too, and we look for that name tag
on some bulletin board. Often, objects will have bulletin boards as part of their makeup,
like a little one on the back of a chair. To read a name tag on it, you use the attribute
notation. E.g.,

    Jons_chair.owner

is an expression that says go find the Johns_chair tag on the wall bulletin board (unless
you have entered another room via a function call) and follow the thread to the object,
then look for a name tag "owner" on the bulleting board that's part of the object, and
follow the connceting thread from that tag wherever it goes, namely to Jon, presumably.

Ok, now Jons_chair.owner is an "attribute chain" and we could write a short "alias" for that,
e.g.,

    jco = Jons_chair.owner

Which would mean going to the big board on the wall and putting a "jco" tag there and connecting
it by a cotton thread to the same place we got by the attribute chain, namely to Jon. So now
there is a nametag jco with a direct connection to Jon.

Now you might think that a handy way to change chair owner would be to do something via jco,
since that tag now leads to the owner, and you might be tempted to write
    jco = Jane
but that would just tie a new thread from the jco tag to wherever the Jane tag leads. It wouldn't
do anything to the notice on the chair's own little bulletin board, where the original owner tag is.
We'd have to write

    Jons_chair.owner = Jane

to make that change. Note that this assignment does not change the cotton thread from the
Jons_chair tag to the chair object. It merely uses that thread to get to the chair, where
the little bulletin board with the owner tag was. Now _that_ tag's cotton thread did get
its connection changed, from Jon to Jane.

Of course after this the Jons_chair tag on the wall becomes a little misleading in
its spelling, even though it would reliably lead to the same chair object, which may
be a different lesson in using names ;-)

>would like a shorter name to bind to an object which might otherwise
>be only referrable to only by a very long chain of attributes.
A long chain of attributes is not a single name, it's an expression involving
a series of different names. Think of each name as a tag on a bulletin board
with a thread leading to the next object, which has its own bulletin board for
name tags, etc., etc.

>
>>>> class A:
>      def __init__(self):
>        self.long_name1=5
>        self.long_name2=15
>      def f1(self):
>        alias1=&self.long_descriptive_name1  # alias1 and alias2 become
>        alias2=&self.long_descriptive_name2  # bound to the same objects as 
>        if alias1>alias2+1: alias1=alias2    # self.long_descriptive_name1 and
>                                             # self.long_descriptive_name2
>                                             # respectively
>
>the last 3 lines replacing the long and rather unreadable 
>(in practice it often gets much worse than shown below):
>
>      if self.long_descriptive_name1>self.long_descriptive_name2+1:
>        self.long_descriptive_name1=self.long_descriptive_name2
>
>If one objects to the & operator to generate an alias, one could always 
>use a function: 
>
>anAlias=alias(self.long_var_name_bound_to_integer)
>
>More comments...?
In terms of name tags and bulletin boards and cotton threads leading to objects,
what does an alias mean? You don't mean two tags whose cotton threads lead to
the same object, ISTM, though that is part of it (the read-only part). I think
the key thing is what you want an assignment to do, using an alias tag as if
it could change the way the original tag connects through its "cotton thread."

An ordinary assignment to a bare name can't do that, because it simply takes
the name and attaches its thread to something else.

There are ways to get a value change, but they all involve more than a bare name
on the left of an assignment. One way is to change an attribute name binding, as we
did with Jons_chair.owner. An object can also have a rack of eyelets to tie cotton
threads to, which lead to objects just like the cotton threads from name tags, except
the eyelets are not identified by name but by their position in the rack, starting
with position zero. If a thing has such an eyelet rack, you can pick up the start
of the i-th cotton thread at the i-th eyelet by writing thing[i]. If you want to
attach yourself to the third eyelet, you can write thing[2] = Jon and that will not
change the connection of the thing's name tag on the wall bulletin board. That is
just used to get to the object with the eyelet rack.

I've belabored a metaphor of bulletin boards (name spaces) and name tags (names)
connected by cotton threads (bound) to objects. I hope it helps show why

    alias = original.way.of.accessing.something

followed by

    alias = 123

doesn't change what you get if you re-evaluate the

    original.way.of.accessing.something

expression again. But that

    lbb = original.way.of.accessing # lbb meaning "last bulletin board in chain"

followed by

    lbb.something = 123

_would_ change what you get re-evaluating

    original.way.of.accessing.something

If you think about the tags and threads you can see why.

Regards,
Bengt Richter




More information about the Python-list mailing list