Это полностью зависит от объекта 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
поведения «s.
+=
действует какextend()
в случае списков.