Python
Operators
Assignment
Programming
Code Efficiency

When is i x different from i i x in Python?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

i += x and i = i + x often produce the same visible result, but they are not always the same operation. The difference shows up when the object supports in-place update through __iadd__, especially for mutable objects and aliasing situations.

Immutable types usually make them look the same

For immutable types such as integers, both forms effectively create a new object:

python
1i = 10
2j = i
3
4i += 5
5print(i, j)

This behaves much like:

python
1i = 10
2j = i
3
4i = i + 5
5print(i, j)

Because integers cannot be modified in place, both versions end up rebinding i to a new integer object while j still points to the old one.

Mutable types can behave differently

Lists are the classic example:

python
1a = [1, 2]
2b = a
3
4a += [3]
5print(a)
6print(b)

This usually mutates the existing list in place, so both a and b now refer to the updated list.

By contrast:

python
1a = [1, 2]
2b = a
3
4a = a + [3]
5print(a)
6print(b)

Here, a + [3] creates a new list and rebinds a to it. b still points to the original list.

That aliasing difference is often the practical answer to the question.

+= tries __iadd__ first

The augmented-assignment form asks the object whether it can perform an in-place update through __iadd__. If the type supports that meaningfully, Python may mutate the existing object.

If not, Python falls back to ordinary addition semantics and rebinding behavior similar to i = i + x.

So the real difference depends on the type's implementation, not just on the syntax itself.

Tuples and the famous surprising case

Tuples are immutable, so += does not mutate them in place. But there is a well-known confusing example involving a tuple containing a mutable element:

python
1t = ([1, 2],)
2
3try:
4    t[0] += [3]
5except TypeError as e:
6    print("error:", e)
7
8print(t)

This raises an error because the tuple slot itself cannot be reassigned, but the list inside may already have been mutated before the failure becomes visible. It is a good reminder that augmented assignment can involve more than one step internally.

Performance is usually a secondary concern

People sometimes ask which form is faster. For mutable sequence types, += can be more efficient because it may extend in place rather than building a new object. But correctness and aliasing behavior matter more than micro-optimization most of the time.

The key question is usually:

  • do I want to mutate the existing object
  • or produce a new one and rebind the name

Choose intentionally when aliasing exists

If multiple variables refer to the same mutable object, += may affect them all through shared state. That can be helpful or dangerous, depending on your intent.

So the most important difference is not the operator symbol. It is whether the underlying object is mutable and whether in-place mutation is visible through aliases.

Common Pitfalls

  • Assuming += and i = i + x are always identical for mutable objects.
  • Forgetting that list += usually mutates in place.
  • Ignoring aliasing and then being surprised when another variable sees the change.
  • Thinking the behavior is determined only by syntax instead of by the type's __iadd__ implementation.
  • Using augmented assignment on nested immutable structures without understanding the side effects.

Summary

  • For immutable types, i += x and i = i + x usually behave the same.
  • For mutable types, += may mutate in place while i = i + x creates a new object.
  • The difference becomes visible when other names alias the same object.
  • '+= works through __iadd__ when the type supports in-place update.'
  • The practical question is whether you want mutation or rebinding.

Course illustration
Course illustration

All Rights Reserved.