Це повністю залежить від об'єкта 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()у випадку зі списками.