2012-05-01 9 views
15

Me encontré con algo que era bastante extraño.¿Por qué + = de una lista dentro de una tupla de Python aumenta TypeError pero modifica la lista de todos modos?

>>> t = ([],) 
>>> t[0].append('hello') 
>>> t 
(['hello'],) 
>>> t[0] += ['world'] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'tuple' object does not support item assignment 
>>> t 
(['hello', 'world'],) 

¿Por qué elevar TypeError y sin embargo, cambiar el list dentro del tuple?

+1

Supongo que tendrías que ver cómo '+ =' se implementa realmente. Parece que en realidad no crea una nueva lista, sino que cambia la lista in situ, esa es la parte '+'. Entonces tienes la tarea, pero como las tuplas son inmutables, esto no está permitido. –

+0

@FelixKling + = funciona de forma similar a append(), es decir, id() de la lista permanece igual. –

+0

También tenga en cuenta que para poder hacer un hash de una tupla, todas sus partes componentes también deben ser manejables. – mgilson

Respuesta

19

A medida que empecé mencionar en el comentario, += realidad modifica la lista en el lugar y luego trata de asignar el resultado a la primera posición en la tupla. Desde el data model documentation:

Estos métodos son llamados a poner en práctica las tareas aritméticas aumentada (+ =, - =, = ,/=, // =,% =, * =, < < =, >> =, & =,^=, | =). Estos métodos deben intentar realizar la operación in situ (modificación de uno mismo) y devolver el resultado (que podría ser, pero no tiene que serlo).

+= es, por tanto, equivalente a:

t[0].extend(['world']); 
t[0] = t[0]; 

Así que la modificación de la lista en contexto no es un problema (paso 1), ya que las listas son mutables, pero asignando el resultado de nuevo a la tupla no es válido (2. paso), y ahí es donde se produce el error.

+2

Y solo para aclarar, la lista existente se concatenó con la lista del RHS, pero la asignación a la tupla falló, pero su referencia al objeto de la lista aún permaneció intacta. Es por eso que ve la lista actualizada y la tupla levantando un 'TypeError'. –

+0

Entendido. Tiene sentido ahora. Gracias. – satran

+0

@Felix Kling pero incluso después de + = el id() de la lista permanece igual, pero el id() de una lista cambia si lo modificamos así, por ejemplo x [0] = x [0] + ['list '], donde x es una lista de listas. –

Cuestiones relacionadas