Could you explain this rebinding (or some other action) on "nums = nums"?

Terry Reedy tjreedy at udel.edu
Tue Dec 1 17:37:34 EST 2015


On 12/1/2015 4:36 PM, Denis McMahon wrote:
> On Tue, 01 Dec 2015 16:18:49 -0500, Terry Reedy wrote:
>
>> On 12/1/2015 3:32 PM, Denis McMahon wrote:
>>> On Tue, 01 Dec 2015 03:32:31 +0000, MRAB wrote:
>>>
>>>> In the case of:
>>>>
>>>>        tup[1] += [6, 7]
>>>>
>>>> what it's trying to do is:
>>>>
>>>>        tup[1] = tup[1].__iadd__([6, 7])
>>>>
>>>> tup[1] refers to a list, and the __iadd__ method _does_ mutate it, but
>>>> then Python tries to put the result that the method returns into
>>>> tup[1].
>>>> That fails because tup itself is a tuple, which is immutable.
>>>
>>> I think I might have found a bug:
>>
>> What you found is an specific example of what MRAB said in general
>> above.
>>
>>> $ python Python 2.7.3 (default, Jun 22 2015, 19:33:41)
>>> [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license"
>>> for more information.
>>>>>> tup = [1,2,3],[4,5,6]
>>>>>> tup
>>> ([1, 2, 3], [4, 5, 6])
>>>>>> tup[1]
>>> [4, 5, 6]
>>>>>> tup[1] += [7,8,9]
>>> Traceback (most recent call last):
>>>     File "<stdin>", line 1, in <module>
>>> TypeError: 'tuple' object does not support item assignment
>>
>> The bug is trying to replace a member of a tuple.  The correct code, to
>> avoid the exception while extending the list, is
>>
>> tup[1].extend([7,8,9])
>>
>>>>>> tup[1]
>>> [4, 5, 6, 7, 8, 9]
>
> You snipped the important bit of my original post, which was the state of
> tup after the TypeError occurred.

No I did not.  The change to tup[1] right there above, after giving the 
correct way to make the change.

> After the error,

>>>> tup[1]
> [4, 5, 6, 7, 8, 9]

This is exactly what I posted.

>>>> tup
> ([1, 2, 3], [4, 5, 6, 7, 8, 9])

This is a repeat of the same thing and adds no new info.

> The "bug" I refer to is that despite giving the TypeError, the tuple
> allowed the assignment of the mutated list to replace the original list.

No it did not.  As MRAB noted, the list is mutated and the attempted 
assignment causes an exeption. This has been discussed before more than 
once ever since augmented *assignment* was introduced.

 >>> tup = ([],[])
 >>> id(tup[1])
711662188872

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

 >>> tup[1] = tup[1].extend([2])
Traceback (most recent call last):
   File "<pyshell#7>", line 1, in <module>
     tup[1] = tup[1].extend([2])
TypeError: 'tuple' object does not support item assignment
 >>> tup[1]
[1, 2]
 >>> id(tup[1])
711662188872

Reading the augmented assignment doc carefully should make it clear that 
"tup[1] += [1]" is the same as "tup[1] = tup[1].extend([2])" except that 
evaluation of "tup[1]" happens just once instead of twice.

-- 
Terry Jan Reedy




More information about the Python-list mailing list