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 afoi 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 += 1para um número inteiro inã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 += yfoi 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 NotImplementedsingleton, 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_tuplefuncionou 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 - tserá ([42, 44], [43])após a execução da linha que gera o erro.