views:

431

answers:

6

Why do these two operations give different results?

>>> c = [1, 2, 3]
>>> c
[1, 2, 3]
>>> c += c
>>> c
[1, 2, 3, 1, 2, 3]
>>> c = [1, 2, 3]
>>> c.append(c)
>>> c
[1, 2, 3, [...]]
>>> 

In the last case there's actually infinite recursion. c[-1] and c are the same. Why is it different with the + operation?

+10  A: 

To explain "why":

The + operation adds the array elements to the original array. The array.append operation inserts the array (or any object) into the end of the original array, which results in a reference to self in that spot (hence the infinite recursion).

The difference here is that the + operation acts specific when you add an array (it's overloaded like others, see this chapter on sequences) by concatenating the element. The append-method however does literally what you ask: append the object on the right-hand side that you give it (the array or any other object), instead of taking its elements.

An alternative

Use extend() if you want to use a function that acts similar to the + operator (as others have shown here as well). It's not wise to do the opposite: to try to mimic append with the + operator for lists (see my earlier link on why).

Little history

For fun, a little history: the birth of the array module in Python in February 1993. it might surprise you, but arrays were added way after sequences and lists came into existence.

Abel
+1 because I always upvote accurate information. Links to official docs are always a plus!
jathanism
Another part of "why": sane people expect `+` to be symmetric: concatenate list with list.
Beni Cherniavsky-Paskin
+1, Good point Beni (while I could consider it just as "sane" to say "the object on the rh side is appended to the array on lh side", but personally find the current behavior more sensible).
Abel
Oh, it's simpler than I thought. I'm not sure what was crossing my mind - the infinite recursion just confused me.
ooboo
+10  A: 

append is appending an element to a list. if you want to extend the list with the new list you need to use extend.

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]
SilentGhost
I believe the question was about "why", not about how to use an alternative...
Abel
I thought it's quite clear *why* the results are different, because operations are not the same! if it would appear that `+` and `extend` produce different results that we'd have something to think about.
SilentGhost
Well, the title and the two questions in the text use the word "why", apparently it wasn't so clear for the asker as it was for you. But perhaps ooboo can shed some light on what (s)he's really after: the answer to "why" or the all too obvious solution from the docs?
Abel
+1: Why I dislike "why" questions: `append` and `+` are different. That's why. I like this answer because offers what do do that makes more sense.
S.Lott
Isn't this site about answering the questions asked? People ask why PHP is called PHP and why `__lt__` could not be overloaded in Python (nowadays it can). Why-questions are the most essential ones but often the trickiest to answer: they ask for the essence, not for a pointer to the manual. And of course: if you dislike a question (I dislike most), then don't answer ;-)
Abel
For further demonstration, maybe show `c += [c]` and `c.append(c[:])` too.
ephemient
@Abel: Why is `a+b != a*b`? They're different operations. That's the answer. "Why" isn't as helpful as other questions, like "How can I append properly?" Or "What's wrong with this append that leads to infinite recursion?" Questions of the form "What do I do to X" or "What went wrong when I did X"? Or "What should I do instead of X" will also help someone learn, but will provide focused, usable, actionable answers.
S.Lott
Interesting side discussion, not sure if we should... but...: If you ask "how can I do X", you answer `obj.X` or `obj+X`. The more elaborate answerer will also explain *why* you should choose either, to teach the asker how to think about it. Yes, I agree, *what*, *how* etc can give very simple, very clear answers, most of the time. *why* is often called the only question with infinite answers.But it teaches us to think. *How do we live is boring* (imo), *why do we live* is much more intriguing. Python started out with the question "why do we need a new language". The answer was the language.
Abel
By the way, we're (I'm) drifting. Before we get all philosophical, have you noticed that the actual asker did explicitly ask *why*. If someone asks for wine, you give him water? I may've totally missed the point of the asker, perhaps his *why* means *what* or *how*. But I think triple *why* means *why*, that's *why*.
Abel
+2  A: 

Python lists are heterogeneous that is the elements in the same list can be any type of object. The expression: c.append(c) appends the object c what ever it may be to the list. In the case it makes the list itself a member of the list.

The expression c += c adds two lists together and assigns the result to the variable c. The overloaded + operator is defined on lists to create a new list whose contents are the elements in the first list and the elements in the second list.

So these are really just different expressions used to do different things by design.

Tendayi Mawushe
+1, much clearer then my explanation ;-)
Abel
@Tendayi, mentioning "There should be one way..." when both `+=` and `extend()` can be applied to lists -- with the same results -- doesn't really make sense. ;-)
Peter Hansen
@Peter Hansen yeah ok point taken :-)
Tendayi Mawushe
+1  A: 

you should use extend()

>>> c=[1,2,3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

other info: http://stackoverflow.com/questions/252703/python-append-vs-extend

ghostdog74
+1  A: 

The method you're looking for is extend(). From the Python documentation:

list.append(x)
    Add an item to the end of the list; equivalent to a[len(a):] = [x].

list.extend(L)
    Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.

list.insert(i, x)
    Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).
Chinmay Kanchi
+1 for good ol' documentation. People should read it more.
jathanism
+1  A: 

See the documentation:

list.append(x)

  • Add an item to the end of the list; equivalent to a[len(a):] = [x].

list.extend(L) - Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.

c.append(c) "appends" c to itself as an element. Since a list is a reference type, this creates a recursive data structure.

c += c is equivalent to extend(c), which appends the elements of c to c.

oefe