146

Why do these two operations (append() resp. +) 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 an infinite recursion. c[-1] and c are the same. Why is it different with the + operation?

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
ooboo
  • 16,259
  • 13
  • 37
  • 32
  • 1
    with all due respect to a viable new question: I rolled back to the original question to keep it clean (1 question per thread, see SO FAQ). Please ask a new one or ask follow-up questions inside the comment-threads below each answer. *Note: your edits are not lost, click the history and you can copy/paste it into a new question.* – Abel Jan 08 '10 at 11:56
  • Similar for `+=`: http://stackoverflow.com/questions/725782/in-python-what-is-the-difference-between-append-and – Ciro Santilli OurBigBook.com Apr 17 '15 at 18:59
  • it seems that it gives different ans, but not like that. If you want to add a value using + operator you have o use [] sign. c += [c] will give you same result as append. – Sharif Chowdhury Aug 31 '17 at 04:34
  • @SharifChowdhury I believe you will get the same result – trustory Feb 16 '20 at 23:34

7 Answers7

177

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 in your case with lists, though with arrays, you'd receive a type error).

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). More on lists below:

Lists

[edit] Several commenters have suggested that the question is about lists and not about arrays. The question has changed, though I should've included this earlier.

Most of the above about arrays also applies to lists:

  • The + operator concatenates two lists together. The operator will return a new list object.
  • List.append does not append one list with another, but appends a single object (which here is a list) at the end of your current list. Adding c to itself, therefore, leads to infinite recursion.
  • As with arrays, you can use List.extend to add extend a list with another list (or iterable). This will change your current list in situ, as opposed to +, which returns a new list.

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
  • 56,041
  • 24
  • 146
  • 247
  • 2
    +1 because I always upvote accurate information. Links to official docs are always a plus! – jathanism Jan 07 '10 at 17:09
  • 12
    Another part of "why": sane people expect `+` to be symmetric: concatenate list with list. – Beni Cherniavsky-Paskin Jan 07 '10 at 17:34
  • 1
    +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 Jan 07 '10 at 18:19
  • if an element is single string, e.g. s = 'word', l = ['this', 'is']. Then l.append(s) and l+s should be the same. Am I correct? – user3512680 Feb 02 '20 at 22:13
  • It is not same, to get same answer, you should use l+[s], otherwise it will throw 'TypeError: can only concatenate list (not "str") to list'. – Abhirami V S Nov 22 '21 at 13:36
  • Why are you linking to the `array.array` docs?? – juanpa.arrivillaga Dec 19 '21 at 00:48
  • @juanpa.arrivillaga, the links go to the `array.html` pages of the reference docs. The `#array.array...` you see in the links are the id of the item in that page. The topic is on arrays, so yeah, that's really all there is to it: convenience links to the docs (of 12yr ago). – Abel Jan 26 '22 at 23:49
  • @Abel although the `array.array` and `list` types work identically in this particular regard, the question was about `list` objects, not `array.array` objects, unless something was changed in an edit? Note, you cannot actually get the equivalent of `[1, 2, 3, [...]]` with `array.array` objects, it would throw a type error if you did `my_array.append(my_array)` – juanpa.arrivillaga Jan 27 '22 at 00:22
  • 1
    @juanpa.arrivillaga, Ah wait, lists vs arrays. I’ll check tomorrow to update my answer a little, I see now, tx! – Abel Feb 12 '22 at 04:38
  • @Abel yeah, unfortunately, the modern docs kind merged the "mutable sequence" operations into one [table summarizing their operations](https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types). But you can also link to the [tutorial which documents some of these operations for list objects specifically](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists) – juanpa.arrivillaga Feb 12 '22 at 05:05
  • Python does not have arrays and it's not a minor issue to conflate them with lists. – Rick O'Shea Aug 31 '22 at 18:01
  • @RickO'Shea the original question and title had no reference to lists (though it could be inferred from the text). Note that Python supports arrays, or at least, it calls them "arrays". I used links to original documentation of Python. But you're right, it may be time to update my answer a little. – Abel Sep 01 '22 at 01:14
32

The concatenation operator + is a binary infix operator which, when applied to lists, returns a new list containing all the elements of each of its two operands. The list.append() method is a mutator on list which appends its single object argument (in your specific example the list c) to the subject list. In your example this results in c appending a reference to itself (hence the infinite recursion).

An alternative to '+' concatenation

The list.extend() method is also a mutator method which concatenates its sequence argument with the subject list. Specifically, it appends each of the elements of sequence in iteration order.

An aside

Being an operator, + returns the result of the expression as a new value. Being a non-chaining mutator method, list.extend() modifies the subject list in-place and returns nothing.

Arrays

I've added this due to the potential confusion which the Abel's answer above may cause by mixing the discussion of lists, sequences and arrays. Arrays were added to Python after sequences and lists, as a more efficient way of storing arrays of integral data types. Do not confuse arrays with lists. They are not the same.

From the array docs:

Arrays are sequence types and behave very much like lists, except that the type of objects stored in them is constrained. The type is specified at object creation time by using a type code, which is a single character.

Community
  • 1
  • 1
Dave
  • 764
  • 7
  • 17
22

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
  • 307,395
  • 66
  • 306
  • 293
  • 4
    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 Jan 07 '10 at 17:12
  • 1
    +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 Jan 07 '10 at 18:52
  • 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 Jan 07 '10 at 18:57
  • For further demonstration, maybe show `c += [c]` and `c.append(c[:])` too. – ephemient Jan 07 '10 at 18:57
  • 2
    @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 Jan 07 '10 at 19:11
  • 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 Jan 07 '10 at 19:57
9

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
  • 25,562
  • 6
  • 51
  • 57
7

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
  • 62,729
  • 22
  • 87
  • 114
3

you should use extend()

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

other info: append vs. extend

Community
  • 1
  • 1
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
2

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
  • 19,298
  • 7
  • 47
  • 66