Це повністю залежить від об'єкта i
.
+=
викликає __iadd__
метод (якщо він існує - повертається назад, __add__
якщо його не існує), тоді як +
викликає __add__
метод 1 або __radd__
метод у кількох випадках 2 .
З точки зору API, __iadd__
він повинен використовуватися для зміни об'єктів, що змінюються на місці (повернення об'єкта, який був мутований), тоді як __add__
повинен повернути новий екземпляр чогось. Для незмінних об'єктів обидва способи повертають новий екземпляр, але __iadd__
додадуть новий екземпляр у поточну область імен з тим самим іменем, що і старий екземпляр. Ось чому
i = 1
i += 1
Здається, приріст i
. Насправді ви отримуєте нове ціле число і присвоюєте йому «зверху» i
- втрачаючи одне посилання на старе ціле число. У цьому випадку i += 1
точно так само, як i = i + 1
. Але з більшістю об'єктів, що змінюються, це вже інша історія:
Як конкретний приклад:
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]
у порівнянні з:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
Зверніть увагу , як в першому прикладі, так b
і a
посилатися на той самий об'єкт, коли я використовую +=
на b
це на самому справі зміни b
(і a
бачить , що зміна теж - В кінці кінців, це посилання на один і той же список). У другому випадку, коли я це роблю b = b + [1, 2, 3]
, це приймає список, на який b
посилається, і з'єднує його з новим списком [1, 2, 3]
. Потім він зберігає об'єднаний список у поточному просторі імен як b
- Без огляду на те, що b
було рядком раніше.
1 У вираженні x + y
, якщо x.__add__
не виконуються або якщо x.__add__(y)
повернення NotImplemented
і x
і y
мають різні типи , то x + y
намагається виклик y.__radd__(x)
. Отже, у випадку, коли у вас є
foo_instance += bar_instance
якщо Foo
не реалізує __add__
або __iadd__
тоді результат тут такий же, як
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 В вираженні foo_instance + bar_instance
, bar_instance.__radd__
буде судимий , foo_instance.__add__
якщо тип bar_instance
є підкласом типу foo_instance
(наприклад issubclass(Bar, Foo)
). Раціональне для цього полягає в тому Bar
, що в деякому сенсі об'єкт "вищого рівня", ніж Foo
так, Bar
повинен отримати можливість переважати Foo
поведінку.
+=
діє якextend()
у випадку зі списками.