Zależy to całkowicie od obiektu i
.
+=
wywołuje __iadd__
metodę (jeśli istnieje - wycofuje się, __add__
jeśli nie istnieje), podczas gdy +
wywołuje __add__
metodę 1 lub __radd__
metodę w kilku przypadkach 2 .
Z perspektywy API, __iadd__
ma być używany do modyfikowania obiektów podlegających mutacji w miejscu (zwracanie zmutowanego obiektu), podczas gdy __add__
powinien zwracać nową instancję czegoś. W przypadku obiektów niezmiennych obie metody zwracają nową instancję, ale __iadd__
umieszczą nową instancję w bieżącej przestrzeni nazw o tej samej nazwie, co stara instancja. Dlatego
i = 1
i += 1
wydaje się zwiększać i
. W rzeczywistości dostajesz nową liczbę całkowitą i przypisujesz ją „na wierzchu” i
- tracąc jedno odniesienie do starej liczby całkowitej. W tym przypadku i += 1
jest dokładnie taki sam jak i = i + 1
. Ale w przypadku większości zmiennych obiektów jest to inna historia:
Jako konkretny przykład:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
w porównaniu do:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
Zauważ, jak w pierwszym przykładzie, ponieważ b
i a
odwoływać się do tego samego obiektu, kiedy używam +=
na b
, to faktycznie zmienia b
(i a
widzi, że zmiany też - Po tym wszystkim, to odwołuje się do tej samej listy). Jednak w drugim przypadku, gdy to zrobię b = b + [1, 2, 3]
, pobiera listę, która b
się do niej odwołuje, i łączy ją z nową listą [1, 2, 3]
. Następnie przechowuje skonkatenowaną listę w bieżącej przestrzeni nazw jako b
- Bez względu na b
poprzednią linię.
1 W wyrażeniu x + y
, jeśli x.__add__
nie jest realizowany lub jeśli x.__add__(y)
powróci NotImplemented
i x
i y
mają różne rodzaje , a następnie x + y
stara się rozmowy y.__radd__(x)
. Tak więc w przypadku, gdy masz
foo_instance += bar_instance
jeśli Foo
się nie implementuje __add__
lub __iadd__
wynik tutaj jest taki sam jak
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 W wyrażeniu foo_instance + bar_instance
, bar_instance.__radd__
będzie próbował wcześniej foo_instance.__add__
czy typ bar_instance
jest podklasą typu foo_instance
(na przykład issubclass(Bar, Foo)
). Racjonalne jest to, bo Bar
jest w pewnym sensie „wyższy poziom” obiekt niż Foo
tak Bar
powinny uzyskać możliwość nadrzędnymi Foo
„s zachowanie.
+=
zachowuje się jakextend()
w przypadku list.