Tuples and immutability

Chris Angelico rosuav at gmail.com
Sun Mar 9 19:13:24 CET 2014


On Mon, Mar 10, 2014 at 4:54 AM, Joshua Landau <joshua at landau.ws> wrote:
> On 28 February 2014 14:43, Chris Angelico <rosuav at gmail.com> wrote:
>> On Sat, Mar 1, 2014 at 1:41 AM, Joshua Landau <joshua at landau.ws> wrote:
>>> Would it be better to add a check here, such that if this gets raised
>>> to the top-level it includes a warning ("Addition was inplace;
>>> variable probably mutated despite assignment failure")?
>>
>> That'd require figuring out whether or not the variable was actually
>> mutated, and that's pretty hard to work out.
>
> It does not. First, the "warning" is actually an attachment to the
> exception so is only shown if the exception is uncaught. This should
> basically never happen in working code. The warning exists only to
> remove likely misunderstanding in these odd cases.
>
> Even if "x = (1,); x[0] += 1" warned "addition was inplace; possible
> mutation occurred" or whatever phrasing you wish, this would only
> cause a quick check of the results.

I think I see what you're saying here. But ignore "top-level"; this
should just be a part of the exception message, no matter what.
Otherwise things that recreate the REPL (like IDLE) or that isolate
two sections of the code (like a web server framework) wouldn't get
the benefit, because the exception's not caught at the true top-level.

>>> x=1,
>>> x[0]+=0
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    x[0]+=0
TypeError: 'tuple' object does not support item assignment

What you're saying is that this should notice that it's doing an
augmented assignment and give some more text. This can be done; all
you need to do is catch the error and reraise it with more info:

>>> try:
    x[0]+=0
except TypeError as e:
    if 'does not support item assignment' in e.args[0]:
        raise TypeError(e.args[0]+"\nAugmented assignment used;
mutation may have occurred.") from None
    raise

Traceback (most recent call last):
  File "<pyshell#16>", line 5, in <module>
    raise TypeError(e.args[0]+"\nAugmented assignment used; mutation
may have occurred.") from None
TypeError: 'tuple' object does not support item assignment
Augmented assignment used; mutation may have occurred.

Now you can look at writing an import hook that does an AST transform,
locating every instance of item assignment and wrapping it like that.
It's certainly possible. I'm not sure how much benefit you'd get, but
it could be done.

ChrisA



More information about the Python-list mailing list