„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 a
otrzymano 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 += 1
Dla liczb całkowitych i
nie 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 += y
bę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 NotImplemented
singleton, 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_tuple
dział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 - t
nastąpi ([42, 44], [43])
po wykonaniu linii, która podnosi błąd.