strange behavor....

Arnaud Delobelle arnodel at gmail.com
Sun Nov 14 17:25:48 EST 2010


Steve Holden <steve at holdenweb.com> writes:

> On 11/14/2010 8:29 AM, Emile van Sebille wrote:
> [...]
>> We all know that _everything_ is a disguised method call and we call the
>> disguised method call that resembles a statement where the LHS is
>> separated from the RHS by a single equals sign assignment.
>
> I think your elided attempt to reconcile the opposing viewpoints on this
> thread is creditworthy. We should not allow our wish to resolve
> conflicting viewpoints blind us to reality, however. What method of a
> does the statement
>
>     a = something
>
> call? I ask in genuine ignorance, and in the knowledge that you may
> indeed be able to point me to such a method.

If "a = something" is compiled to "STORE_NAME" and the statement is
executed in a context where locals() is a custom dictionary then it is
possible that the statement will call the custom __setitem__ method of
the locals:

>>> class mydict(dict):
...     def __setitem__(self, key, val):
...         print "assigning %r to %r" % (val, key)
...         super(mydict, self).__setitem__(key, val)
... 
>>> d = mydict()
>>> exec "a=2" in d
assigning 2 to 'a'
>>> d['a']
2

But note that:

>>> exec "global a; a = 3" in d
>>> d['a']
3

So even if the globals() dictionary is custom, its __setitem__ method is
*not* called.

Below is a summary of what methods are called depending on the opcode
executed:

OPCODE          Assignment type Method call
=============== =============== ===============================================
STORE_SLICE     a[?:?] = b      calls a.__setslice__(...) or a.__setitem__(...)
STORE_SUBSCR    a[x] = b        calls a.__setitem__(x, b)

STORE_ATTR      a.x = b         calls a.__setattr__("x", b)

STORE_NAME      a = b           calls locals().__setitem__("a", b)
STORE_GLOBAL    a = b           calls dict.__setitem__(globals(), "a", b)
STORE_FAST      a = b           doesn't call any method
STORE_DEREF     a = b           doesn't call any method       

So you can see that a[...] = b and a.x = b *always* call a method that
can be overriden, whereas a = b *almost* never does.  The only exception
is when the opcode "STORE_NAME" is executed.  I'm not sure when
something gets compiled to "STORE_NAME", but I can't think of many
examples apart from when one uses the "exec" statement.  Perhaps someone
can enlighten me here.

>
> I would prefer to think of
>
>     a = something
>
> and
>
>     lst[i] = something
>
> as in some sense different, because I see names as referencing locations
> in a namespace. Perhaps you can help to unify my perceptions.

I think that you are correct, with the "STORE_NAME" caveat.

-- 
Arnaud



More information about the Python-list mailing list