„Rozszerzone” operatory przypisania, takie jak, +=zostały wprowadzone w Pythonie 2.0, który został wydany w październiku 2000 r. Projekt i uzasadnienie opisano w PEP 203 . Jednym z deklarowanych celów tych operatorów było wsparcie operacji na miejscu. Pisanie
a = [1, 2, 3]
a += [4, 5, 6]
ma aktualizować listę a na miejscu . Ma to znaczenie, jeśli istnieją inne odwołania do listy a, np. Kiedy aotrzymano ją jako argument funkcji.
Jednak operacja nie zawsze może mieć miejsce, ponieważ wiele typów Pythona, w tym liczby całkowite i łańcuchy, są niezmienne , więc np. i += 1Dla liczb całkowitych inie można operować w miejscu.
Podsumowując, operatorzy rozszerzonego przypisania mieli działać, gdy to możliwe, i tworzyć nowy obiekt w inny sposób. Aby ułatwić osiągnięcie tych celów projektowych, określono wyrażenie, które x += ybędzie zachowywać się w następujący sposób:
- Jeśli
x.__iadd__jest zdefiniowane, x.__iadd__(y)jest oceniane.
- W przeciwnym razie, jeśli
x.__add__jest implementowany, x.__add__(y)jest oceniany.
- W przeciwnym razie, jeśli
y.__radd__jest implementowany, y.__radd__(x)jest oceniany.
- W przeciwnym razie podnieś błąd.
Pierwszy wynik uzyskany w tym procesie zostanie przypisany z powrotem x(chyba że wynikiem jest NotImplementedsingleton, w którym to przypadku wyszukiwanie jest kontynuowane w następnym kroku).
Ten proces pozwala na wdrożenie typów obsługujących modyfikacje w miejscu __iadd__(). Typy, które nie obsługują modyfikacji w miejscu, nie muszą dodawać żadnych nowych magicznych metod, ponieważ Python automatycznie do nich wróci x = x + y.
W końcu przejdźmy do twojego rzeczywistego pytania - dlaczego możesz dodać krotkę do listy za pomocą rozszerzonego operatora przypisania. Z pamięci historia tego była mniej więcej taka: list.__iadd__()Metoda została zaimplementowana, aby po prostu wywołać już istniejącą list.extend()metodę w Pythonie 2.0. Kiedy iteratory zostały wprowadzone w Pythonie 2.1, list.extend()metoda została zaktualizowana, aby akceptować dowolne iteratory. Efektem końcowym tych zmian było, że my_list += my_tupledziałało począwszy od Python 2.1. Jednak list.__add__()metoda ta nigdy nie powinna wspierać arbitralnych iteratorów jako argumentu po prawej stronie - uważano to za nieodpowiednie dla silnie typowanego języka.
Osobiście uważam, że implementacja rozszerzonych operatorów okazała się w Pythonie zbyt skomplikowana. Ma wiele zaskakujących skutków ubocznych, np. Ten kod:
t = ([42], [43])
t[0] += [44]
Druga linia podnosi się TypeError: 'tuple' object does not support item assignment, ale operacja i tak jest pomyślnie wykonana - tnastąpi ([42, 44], [43])po wykonaniu linii, która podnosi błąd.