8

I'm surely not the Python guru I'd like to be and I mostly learn studying/experimenting in my spare time, it is very likely I'm going to make a trivial question for experienced users... yet, I really want to understand and this is a place that helps me a lot.

Now, after the due premise, Python documentation says:

4.6.3. Mutable Sequence Types

s.append(x) appends x to the end of the sequence (same as s[len(s):len(s)] = [x])

[...]

s.insert(i, x) inserts x into s at the index given by i (same as s[i:i] = [x])

and, moreover:

5.1. More on Lists

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

[...]

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).

So now I'm wondering why there are two methods to do, basically, the same thing? Wouldn't it been possible (and simpler) to have just one append/insert(x, i=len(this)) where the i would have been an optional parameter and, when not present, would have meant add to the end of the list?

danicotra
  • 1,333
  • 2
  • 15
  • 34
  • 5
    `append` can insert only at the end. Its a special case of `insert`. – thefourtheye Jul 30 '15 at 19:17
  • 5
    `append` takes constant time to run, and `insert` takes linear time to run, too; see [TimeComplexity](https://wiki.python.org/moin/TimeComplexity) on the Python Wiki. (*Linear time*, or *O(n)*, means the time it takes to `insert` a value scales with the size of the list, while `append` is always very fast.) – Lynn Jul 30 '15 at 19:19
  • 1
    It would be a simpler API to have one method but appending to a list typically has different performance characteristics compared to inserting in the middle or front, see http://stackoverflow.com/questions/7776938/python-insert-vs-append. You could choose to use only insert and not be bothered with append. –  Jul 30 '15 at 19:20
  • @thefourtheye : yes, I understand that... then why not simply make the index parameter optional with `insert` ? – danicotra Jul 30 '15 at 19:20
  • 1
    @Mauris That would make a fine answer. – GolezTrol Jul 30 '15 at 19:21
  • @danicotra Because it would likely worsen the performance, and because having two different methods is a _reminder_ that one has worse performance than the other. – Two-Bit Alchemist Jul 30 '15 at 19:21
  • @Mauris , @ nightshadequeen, @ Tris Nefzger ... ah, ok, I think I got it then, it is to make sure of the availability of a method to use when peremptory "performances-to-the-max" do make a big difference... – danicotra Jul 30 '15 at 19:28
  • @Mauris : I agree with GolezTrol, wouldn't you post an answer? – danicotra Jul 30 '15 at 19:33

2 Answers2

6

The difference between append and insert here is the same as in normal usage, and in most text editors. Append adds to the end of the list, while insert adds in front of a specified index. The reason they are different methods is both because they do different things, and because append can be expected to be a quick operation, while insert might take a while depending on the size of the list and where you're inserting, because everything after the insertion point has to be reindexed.

I'm not privy to the actual reasons insert and append were made different methods, but I would make an educated guess that it is to help remind the developer of the inherent performance difference. Rather than one insert method, with an optional parameter, which would normally run in linear time except when the parameter was not specified, in which case it would run in constant time (very odd), a second method which would always be constant time was added. This type of design decision can be seen in other places in Python, such as when methods like list.sort return None, instead of a new list, as a reminder that they are in-place operations, and not creating (and returning) a new list.

Two-Bit Alchemist
  • 17,966
  • 6
  • 47
  • 82
2

The other answer is great -- but another fundamental difference is that insert is much slower:

$ python -m timeit -s 'x=list(range(100000))' 'x.append(1)'
10000000 loops, best of 3: 0.19 usec per loop
$ python -m timeit -s 'x=list(range(100000))' 'x.insert(len(x), 1)'
1000000 loops, best of 3: 0.514 usec per loop

It's O(n), meaning the time it takes to insert at len(x) scales linearly with the size of your list. append is O(1), meaning it's always very fast, no matter how big your list is.

Lynn
  • 10,425
  • 43
  • 75
  • 1
    I did try to touch on this in my answer, but this is more in depth and I like your examples. You should add this case: `python -m timeit -s 'x=list(range(100000))' 'x.insert(0, 1)'`. When I ran this I got similar results to yours, with inserting at the end being about twice as slow as append. For inserting at the beginning, which is its real worst case, it was ***160 times slower***. I realize this is a bit apples to oranges, as this isn't something append can do in-place, but it really helps to highlight where insert actually gets slow. – Two-Bit Alchemist Jul 31 '15 at 16:02