Augmented assignment (was Re: Something in the function tutorial confused me.)

Aahz aahz at pythoncraft.com
Sat Aug 11 09:32:42 EDT 2007


In article <m3hvi.37606$G23.6240 at newsreading01.news.tds.net>,
Neil Cerutti  <horpner at yahoo.com> wrote:
>On 2007-08-11, Alex Martelli <aleax at mac.com> wrote:
>> Neil Cerutti <horpner at yahoo.com> wrote:
>>    ...
>>> The Python Language Reference seems a little confused about the
>>> terminology.
>>> 
>>>   3.4.7 Emulating numeric types
>>>   6.3.1 Augmented assignment statements
>>> 
>>> The former refers to "augmented arithmetic operations", which I
>>> think is a nice terminology, since assignment is not necessarily
>>> taking place. Then the latter muddies the waters.
>>
>> Assignment *IS* "necessarily taking place"; if you try the augmented
>> assignment on something that DOESN'T support assignment, you'll get an
>> exception.  Consider:
>>
>>>>> tup=([],)
>>>>> tup[0] += ['zap']
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in <module>
>> TypeError: 'tuple' object does not support item assignment
>>
>> Tuples don't support item ASSIGNMENT, and += is an ASSIGNMENT,
>> so tuples don't allow a += on any of their items.
>>
>> If you thought that += wasn't an assignment, this behavior and
>> error message would be very problematic; since the language
>> reference ISN'T confused and has things quite right, this
>> behavior and error message are perfectly consistent and clear.
>
>Thanks for the correction. I was under the illusion that sometimes
>augmented assignment would instead mutate the object.

Although Alex is essentially correct, the situation is a bit more complex
and you are correct that augmented assignment allows the object to decide
whether to mutate in place.  However, the critical part of Alex's point
is what you need to focus on: it's the *tuple* in Alex's example that
intercepts the assignment call, not the list contained in the tuple.

Obviously, you can easily work around it:

>>> t = ([],)
>>> l = t[0]
>>> l += ['foo']
>>> t
(['foo'],)

And this proves that you are correct about the list getting mutated in
place and reflected back in the tuple.  Generally speaking, augmented
assignment with nested container objects is a Bad Idea IMO -- split out
the bits you want to work with.
-- 
Aahz (aahz at pythoncraft.com)           <*>         http://www.pythoncraft.com/

"And if that makes me an elitist...I couldn't be happier."  --JMS



More information about the Python-list mailing list