Os operadores de atribuição "aumentada", como +=
foram introduzidos no Python 2.0, lançado em outubro de 2000. O design e a lógica estão descritos no PEP 203 . Um dos objetivos declarados desses operadores era o suporte às operações no local. Escrita
a = [1, 2, 3]
a += [4, 5, 6]
deve atualizar a lista a
no local . Isso importa se houver outras referências à lista a
, por exemplo, quando a
foi recebido como argumento de função.
No entanto, a operação nem sempre pode acontecer no local, pois muitos tipos de Python, incluindo números inteiros e seqüências de caracteres, são imutáveis , portanto, por exemplo, i += 1
para um número inteiro i
não é possível operar no local.
Em resumo, os operadores de atribuição aumentada deveriam trabalhar no local quando possível e criar um novo objeto de outra forma. Para facilitar esses objetivos de design, a expressão x += y
foi especificada para se comportar da seguinte maneira:
- Se
x.__iadd__
definido, x.__iadd__(y)
é avaliado.
- Caso contrário, se
x.__add__
implementado, x.__add__(y)
é avaliado.
- Caso contrário, se
y.__radd__
implementado, y.__radd__(x)
é avaliado.
- Caso contrário, gere um erro.
O primeiro resultado obtido por esse processo será atribuído de volta a x
(a menos que esse resultado seja o NotImplemented
singleton, nesse caso a pesquisa continua com a próxima etapa).
Esse processo permite que tipos que suportam modificações no local sejam implementados __iadd__()
. Tipos que não suportam modificação no local não precisam adicionar novos métodos mágicos, já que o Python volta automaticamente ao essencial x = x + y
.
Então, finalmente, vamos à sua pergunta real - por que você pode adicionar uma tupla a uma lista com um operador de atribuição aumentada. De memória, o histórico disso era mais ou menos assim: O list.__iadd__()
método foi implementado para simplesmente chamar o list.extend()
método já existente no Python 2.0. Quando os iteradores foram introduzidos no Python 2.1, o list.extend()
método foi atualizado para aceitar iteradores arbitrários. O resultado final dessas mudanças foi o que my_list += my_tuple
funcionou a partir do Python 2.1. O list.__add__()
método, no entanto, nunca deveria suportar iteradores arbitrários como o argumento da direita - isso foi considerado inadequado para uma linguagem fortemente tipada.
Pessoalmente, acho que a implementação de operadores aumentados acabou sendo um pouco complexa em Python. Tem muitos efeitos colaterais surpreendentes, por exemplo, este código:
t = ([42], [43])
t[0] += [44]
A segunda linha aumenta TypeError: 'tuple' object does not support item assignment
, mas a operação é executada com êxito de qualquer maneira - t
será ([42, 44], [43])
após a execução da linha que gera o erro.