Los operadores de asignación "aumentada" como +=
se introdujeron en Python 2.0, que se lanzó en octubre de 2000. El diseño y la justificación se describen en PEP 203 . Uno de los objetivos declarados de estos operadores era el apoyo de las operaciones en el lugar. Escritura
a = [1, 2, 3]
a += [4, 5, 6]
se supone que actualiza la lista a
en su lugar . Esto es importante si hay otras referencias a la lista a
, por ejemplo, cuándo a
se recibió como argumento de función.
Sin embargo, la operación no siempre puede ocurrir en el lugar, ya que muchos tipos de Python, incluidos los enteros y las cadenas, son inmutables , por lo que, por ejemplo, i += 1
un entero i
no puede funcionar en su lugar.
En resumen, se suponía que los operadores de asignación aumentada trabajarían en su lugar cuando fuera posible y, de lo contrario, crearían un nuevo objeto. Para facilitar estos objetivos de diseño, x += y
se especificó que la expresión se comportara de la siguiente manera:
- Si
x.__iadd__
se define, x.__iadd__(y)
se evalúa.
- De lo contrario, si
x.__add__
se implementa x.__add__(y)
se evalúa.
- De lo contrario, si
y.__radd__
se implementa y.__radd__(x)
se evalúa.
- De lo contrario, generar un error.
El primer resultado obtenido por este proceso se asignará nuevamente a x
(a menos que ese resultado sea el NotImplemented
singleton, en cuyo caso la búsqueda continúa con el siguiente paso).
Este proceso permite la implementación de tipos que admiten la modificación en el lugar __iadd__()
. Los tipos que no admiten la modificación en el lugar no necesitan agregar ningún método mágico nuevo, ya que Python recurrirá automáticamente a esencialmente x = x + y
.
Así que finalmente lleguemos a su pregunta real: por qué puede agregar una tupla a una lista con un operador de asignación aumentada. De memoria, la historia de esto fue más o menos así: el list.__iadd__()
método se implementó simplemente para llamar al list.extend()
método ya existente en Python 2.0. Cuando se introdujeron los iteradores en Python 2.1, el list.extend()
método se actualizó para aceptar iteradores arbitrarios. El resultado final de estos cambios fue que my_list += my_tuple
funcionó a partir de Python 2.1. El list.__add__()
método, sin embargo, nunca se debe apoyar iteradores arbitrarias como el argumento de la derecha - esto fue considerado inapropiado para un lenguaje fuertemente tipado.
Personalmente, creo que la implementación de operadores aumentados terminó siendo demasiado compleja en Python. Tiene muchos efectos secundarios sorprendentes, por ejemplo, este código:
t = ([42], [43])
t[0] += [44]
La segunda línea se eleva TypeError: 'tuple' object does not support item assignment
, pero la operación se realiza con éxito de todos modos , t
será ([42, 44], [43])
después de ejecutar la línea que genera el error.