a += b is not the same as a = a + b
Tahmid Hossain
Posted on December 2, 2020
In python a += b
is not equivalent as a = a + b
. They do not behave the same always. Consider the following:
>>> a = [1, 2, 3]
>>> b = a
>>> a += [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[1, 2, 3, 4, 5, 6]
>>> a = [1, 2, 3]
>>> b = a
>>> a = a + [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[1, 2, 3]
What happend here:
-
a += b
modified the list in-place. That means it extended a such that a and b had reference to the same list. -
a = a + b
expression created a new list and changed a 's reference to that new list. And b refered to the old list. Why it happened? Here comes how python implements+
and+=
operators. When you use+
operator python calls the__add__
special method. On the other hand+=
operator calls the__iadd__
special method, and if__iadd__
is not available only then it uses__add__
method. See below:
class MyList (list):
def __add__ (self, other):
print ("__add__ has been called")
return super (MyList, self).__add__ (other)
def __iadd__ (self, other):
print ("__iadd__ has been called")
return super (MyList, self).__iadd__ (other)
Now, run the below code:
a = MyList ([1, 2, 3])
b = a
a = a + b
It gives following output:
__add__ has been called
Now, run the below code:
a = MyList ([1, 2, 3])
b = a
a += b
It gives the following output:
__iadd__ has been called
The __iadd__
special method is for an inplace addition. That is it mutates the object that it acts on (in a += b
__iadd__
mutates a). On the other hand,__add__
method returns a new object (in a = a + b
we assigned __add__
's returned object into a).
__iadd__
is only available for mutable types. That's why for immutable types like integers (int
), strings (str
) and tuple
both +
and +=
are equivalent as they both calles __add__
. And this is what lets you use +=
on immutable types.
Now, let's see another difference between +
and +=
. Consider the following:
>>> a = [1, 2, 3]
>>> b = "hello"
>>> a + b
TypeError: can only concatenate list (not "str") to list
>>> a += b
>>> a
[1, 2, 3, 'h', 'e', 'l', 'l', 'o']
Here a + b
gives TypeError
. Because +
operator is symmetrical. So, we can't add a list
and str
. But +=
operator is obviously not symmetrical. It is equivalent to list.extend
, which iterates over the second operand. See below:
class MyStr (str):
def __iter__ (self):
print ("__iter__ has been called")
return super (MyStr, self).__iter__()
a = [1, 2, 3]
b = "hello"
a += b
It gives following output:
__iter__ has been called
So, for types that support both __add__
and __iadd__
you therefore have to be careful which one you use.
Posted on December 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.