[Python-Dev] chained assignment weirdity
Terry Reedy
tjreedy at udel.edu
Tue Nov 6 10:24:37 CET 2012
On 11/6/2012 1:18 AM, Chris Withers wrote:
> Hi All,
>
> I bumped into this using Michael Foord's Mock library.
> It feels like a bug to me, but thought I'd ask here before logging one
> in the tracker in case people know that we won't be able to fix it:
>
> On 05/11/2012 13:43, Michael Foord wrote:
>>
>>>>>>> class Foo(object):
>>>> ... def __setattr__(s, k, v):
>>>> ... print k
>>>> ...
>>>>>>> f = Foo()
>>>>>>>
>>>>>>> f.g = f.x = 3
>>>> g
>>>> x
>>>
>>> Hmm, that's definitely counter-intuitive. Worth raising on python-dev?
>>
>> Well, I guess "it's always been that way", so changing it would be
>> backwards incompatible. Feel free to raise it though. :-)
You are expecting a chained assignment a = b = c to be parsed as
a = (b = c), as in C and as it should be if assignment is an expression.
But in Python it is not. The right association would be meaningless
since (b = c) has no value to be assigned to a.
Python actually parses the chained assignment as (a =) (b =) c.
The relevant grammar production is "assignment_stmt ::=
(target_list "=")+ (expression_list | yield_expression)".
The explanation after the grammar begins with this sentence.
"An assignment statement evaluates the expression list (remember that
this can be a single expression or a comma-separated list, the latter
yielding a tuple) and assigns the single resulting object to each of the
target lists, from left to right."
In other words, in my example, c is assigned to a then b. Please do not
report documented behavior on the tracker as a bug (and don't encourage
people to). If you think the above is not clear enough, you *can*
suggest improvement. Perhaps add an example and explanation such as
a = b, (c,d), *e, f = 1, (2, 3), 4, 5, 6
"The tuple on the right is first assigned to a and then unpacked to b,
c, d, e, and f, giving them the values 1, 2, 3, [4, 5], and 6."
--
Terry Jan Reedy
More information about the Python-Dev
mailing list