Why does b+=(4,) work and b = b + (4,) doesn't work when b is a list? Why does b+=(4,) work and b = b + (4,) doesn't work when b is a list? python-3.x python-3.x

Why does b+=(4,) work and b = b + (4,) doesn't work when b is a list?


The problem with "why" questions is that usually they can mean multiple different things. I will try to answer each one I think you might have in mind.

"Why is it possible for it to work differently?" which is answered by e.g. this. Basically, += tries to use different methods of the object: __iadd__ (which is only checked on the left-hand side), vs __add__ and __radd__ ("reverse add", checked on the right-hand side if the left-hand side doesn't have __add__) for +.

"What exactly does each version do?" In short, the list.__iadd__ method does the same thing as list.extend (but because of the language design, there is still an assignment back).

This also means for example that

>>> a = [1,2,3]>>> b = a>>> a += [4] # uses the .extend logic, so it is still the same object>>> b # therefore a and b are still the same list, and b has the `4` added[1, 2, 3, 4]>>> b = b + [5] # makes a new list and assigns back to b>>> a # so now a is a separate list and does not have the `5`[1, 2, 3, 4]

+, of course, creates a new object, but explicitly requires another list instead of trying to pull elements out of a different sequence.

"Why is it useful for += to do this? It's more efficient; the extend method doesn't have to create a new object. Of course, this has some surprising effects sometimes (like above), and generally Python is not really about efficiency, but these decisions were made a long time ago.

"What is the reason not to allow adding lists and tuples with +?" See here (thanks, @splash58); one idea is that (tuple + list) should produce the same type as (list + tuple), and it's not clear which type the result should be. += doesn't have this problem, because a += b obviously should not change the type of a.


They are not equivalent:

b += (4,)

is shorthand for:

b.extend((4,))

while + concatenates lists, so by:

b = b + (4,)

you're trying to concatenate a tuple to a list


When you do this:

b += (4,)

is converted to this:

b.__iadd__((4,)) 

Under the hood it calls b.extend((4,)), extend accepts an iterator and this why this also work:

b = [1,2,3]b += range(2)  # prints [1, 2, 3, 0, 1]

but when you do this:

b = b + (4,)

is converted to this:

b = b.__add__((4,)) 

accept only list object.