Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List extending strange behaviour [duplicate]

Tags:

python

list

Found interesting thing in Python (2.7) that never mentioned before.

This:

a = []
a += "a"

does work and result is:

>>> a
>>> ["a"]

But

a = []
a = a + "a"

gives

>>> TypeError: can only concatenate list (not "str") to list

Can someone explain why? Thanks for your answers.

like image 300
alexvassel Avatar asked Dec 16 '12 18:12

alexvassel


2 Answers

Python distinguishes between the + and += operators and provides separate hooks for these; __add__ and __iadd__. The list() type simply provides a different implementation for the latter.

It is more efficient for lists to implement these separately; __add__ has to return a completely new list, while __iadd__ can just extend self then return self.

In the C code, __iadd__ is implemented by list_inplace_concat(), which simply calls listextend(), or, in python code, [].extend(). The latter takes any sequence, by design.

The __add__ method on the other hand, represented in C by list_concat, only takes a list as input, probably for efficiency's sake; it can loop directly over the internal C array and copy items over to the new list.

In conclusion, the reason __iadd__ accepts any sequence is because when PEP 203 (the Augmented Add proposal) was implemented, for lists it was simplest just to reuse the .extend() method.

like image 136
Martijn Pieters Avatar answered Oct 14 '22 21:10

Martijn Pieters


If a is a list, a + x only works if x is also list, whereas a += x works for any iterable x.

The following might help understand it:

In [4]: a = []

In [5]: a += "abc"

In [6]: a
Out[6]: ['a', 'b', 'c']

The key is that "a" and "abc" are iterable, which is what enables their use on the right-hand side of +=.

This doesn't work for + because the latter requires both operands to be of the same type (see the manual).

To write the same thing using +, you have to expand the iterable:

In [7]: a = []

In [8]: a = a + list("abc")

In [9]: a
Out[9]: ['a', 'b', 'c']

In other words, += is more general than + when applied to lists.

like image 37
NPE Avatar answered Oct 14 '22 19:10

NPE