Is it possible to override += in Python?
4 Answers
Yes, override the __iadd__
method. Example:
def __iadd__(self, other):
self.number += other.number
return self

- 1,498
- 1
- 27
- 39

- 349,597
- 67
- 533
- 578
-
52You shouldn't implement `__iadd__` if your class represents immutable objects. In that case just implement `__add__` which will be used to override `+=` instead. For example you can use `+=` on immutable types such as strings and integers, which couldn't be done using `__iadd__`. – Scott Griffiths Jan 04 '10 at 23:26
-
@ScottGriffiths, so are you saying that if you've implemented `__add__` you don't necessarily have to implement `__iadd__`? I read the duplicate question you linked but I just got confused because I don't understand why you would implement `__add__` so that it mutates the object – Josie Thompson Mar 05 '16 at 22:25
-
1@ScottGriffiths meant ask "you don't necessarily have to implement `__iadd__` __to use +=__?" – Josie Thompson Mar 05 '16 at 22:37
-
15@JosieThompson: If you don't implement `__iadd__` then it will use `__add__` if available, which is usually just fine. So in that case `a += b` would be equivalent to `a = a + b`, which assigns a new value to `a` instead of changing `a` itself. Having a separate `__iadd__` is typically a nice optimisation rather than something you need to use the `+=` operator. – Scott Griffiths Mar 07 '16 at 11:50
-
1@ScottGriffiths Is the same true for `__imul__`? – Chris_Rands Jun 15 '18 at 12:24
-
@Chris_Rands: Yes the same goes for `__imul__` and other in-place operators (`__isub__`, `__idiv__` etc.) They should only be defined for mutable objects, and if not defined all will fall back to the standard operators in the same way. So `a *= 2` is equivalent to `a = a * 2` if `__imul__` is not defined for the type of `a`. – Scott Griffiths Jul 04 '23 at 17:26
In addition to what's correctly given in answers above, it is worth explicitly clarifying that when __iadd__
is overriden, the x += y
operation does NOT end with the end of __iadd__
method.
Instead, it ends with x = x.__iadd__(y)
. In other words, Python assigns the return value of your __iadd__
implementation to the object you're "adding to", AFTER the implementation completes.
This means it is possible to mutate the left side of the x += y
operation so that the final implicit step fails. Consider what can happen when you are adding to something that's within a list:
>>> x[1] += y # x has two items
Now, if your __iadd__
implementation (a method of an object at x[1]
) erroneously or on purpose removes the first item (x[0]
) from the beginning of the list, Python will then run your __iadd__
method) & try to assign its return value to x[1]
. Which will no longer exist (it will be at x[0]
), resulting in an ÌndexError
.
Or, if your __iadd__
inserts something to beginning of x
of the above example, your object will be at x[2]
, not x[1]
, and whatever was earlier at x[0]
will now be at x[1]
and be assigned the return value of the __iadd__
invocation.
Unless one understands what's happening, resulting bugs can be a nightmare to fix.

- 4,796
- 2
- 22
- 31
-
6do you happen to know why `__iadd__` is designed like that? i.e. why it assigns the return value rather than just settling with in-place mutation? – joel Jun 24 '19 at 21:57
-
4@joel Because that's how it must work with immutable types such as `str` and `int`, and, more importantly, `tuple` and `namedtuple`. – Liz Av Apr 07 '21 at 19:53
In addition to overloading __iadd__
(remember to return self!), you can also fallback on __add__
, as x += y will work like x = x + y. (This is one of the pitfalls of the += operator.)
>>> class A(object):
... def __init__(self, x):
... self.x = x
... def __add__(self, other):
... return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False
It even trips up experts:
class Resource(object):
class_counter = 0
def __init__(self):
self.id = self.class_counter
self.class_counter += 1
x = Resource()
y = Resource()
What values do you expect x.id
, y.id
, and Resource.class_counter
to have?

- 1
- 1
-
11Your second example has nothing to do with iadd or +=. The same result occurs if you use self.class_counter = self.class_counter + 1 It's just a scoping issue, using self when Resource should be used. – FogleBird Jun 26 '09 at 02:42
-
It's an example of how using += can lead to problems. If you're overloading __iadd__, then you're opening users of your class (including yourself) to this, and, at the very least, you should know the issue exists beforehand. – Jun 26 '09 at 04:06
-
5@FogleBird: It is a gotcha because `foo += bar` can either mean "mutate the existing object that `foo` refers to" or "assign `foo` to the object resulting from the expression `foo + bar`". And which happens depends on whether `foo` has an `__iadd__` method. – Claudiu Dec 18 '16 at 07:34
-
In your example, `foo` is just a number. It's not an instance of the class you're defining. You never call either `+` or `+=` with the `Resource` class. It's a gotcha, but it's not related to having or not having a `__iadd__` method defined or not defined for `Resource`. – John Nov 14 '22 at 16:36
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
For instance, to execute the statement x += y, where x is an instance of a class that has an __iadd__() method, x.__iadd__(y) is called.

- 45,913
- 27
- 138
- 182