Python 3000 idea: reversing the order of chained assignments

Erik Johnson nobody at invalid.com
Thu Mar 22 18:22:40 CET 2007


"Virgil Dupras" <hardcoded.software at gmail.com> wrote in message
news:1174529622.860892.133800 at d57g2000hsg.googlegroups.com...
> > >>>> class Node:
> > > ...     pass
> > > ...
> > >>>> node = Node()
> > >>>> nextnode = Node()
> > >>>> backup_node = node
> > >>>> node = node.next = nextnode
> > >>>> node.next is node
> > > True
> > >>>> hasattr(backup_node,'next')
> > > False


    Well, I think I am thoroughly confused now. I am a lot less experienced
that most of the people posting in this thread, so perhaps that is to be
expected, but I actually thought I understood Python fairly well. Maybe I am
fooling myself...

  Let me rename some variables in the code above to something a little
easier to follow:

>>> class Node: pass
...
>>> n1 = Node()
>>> n2 = Node()
>>> n3 = n1

At this point I beleive I've got the same thing above, just with different
reference names.  Namely, I have two objects, and three references, the
first and third reference now both referring to the first object, the second
reference referring to the second object:

>>> n1
<__main__.Node instance at 0x7ff1d20c>
>>> n2
<__main__.Node instance at 0x7ff1d10c>
>>> n3
<__main__.Node instance at 0x7ff1d20c>

The discussion is about multiple assignments. Virgil's example should be
equivalent to:

n1 = n1.next = n2

    If assignment were left to right, (i.e., n1 = n1.next, followed by
n1.next = n2), then I would expect to get an attribute error because n1
hasn't had the 'next' attribute attached to it yet.  That's not what
happens, so the other interpretation is that the statement above is
equivalent to: n1.next = n2; n1= n1.next (except that n1.next is only
evaluated once, but that doesn't matter here). Right?  That is, first object
'n1' gets a new attribute, the value of which is a reference to object n2,
and then, the name 'n1' is rebound to be a reference to object n2 (note that
the object n1 was previously referencing should still be available via name
'n3', and being a mutable object, the new attribute should be visible via
'n3', right?

    I didn't yet execute the statement above (I just typed it in this
post) - let's first check the objects and attributes for what we have prior
to this confusing statement:

>>> n1
<__main__.Node instance at 0x7ff1d20c>
>>> n2
<__main__.Node instance at 0x7ff1d10c>
>>> n3
<__main__.Node instance at 0x7ff1d20c>
>>> dir(n1)
['__doc__', '__module__']
>>> dir(n2)
['__doc__', '__module__']
>>> dir(n3)
['__doc__', '__module__']

Right... no suprises there. Let's execute that funky statement...

>>> n1 = n1.next = n2
>>>

We would expect n1 to reference n2 now (my object at ...d10c), which it
does:

>>> n1
<__main__.Node instance at 0x7ff1d10c>

And we would expect n3 to still be referencing the object at ...d20c, which
it also still does:

>>> n3
<__main__.Node instance at 0x7ff1d20c>

And we would expect  (or I should say "I would expect") n3 to now have a
'next' attribute:

>>> dir(n3)
['__doc__', '__module__']

    It doesn't, which is what Virgil previously pointed out. I'm not quite
following the whole discussion (nor the syntax diagrams), so sorry if this
was already explined - could someone try again: why is it that n3 here
doesn't get the 'next' attribute?

    Now here's the part that totally floors me: what would you expect to be
the attributes on n2 (the object on the far-right of the multi-way
assignment statement)? We've made no assigment statements to anything about
n2. They should be the same as before, right?

>>> dir(n2)
['__doc__', '__module__', 'next']
>>> n2.next
<__main__.Node instance at 0x7ff1d10c>
>>> n2
<__main__.Node instance at 0x7ff1d10c>
>>>

 DUH.... I'm about speechless... Is it just me being dense, or is there some
obvious reason why one would expect this?





More information about the Python-list mailing list