list.append()
appends to the end of a list. This explains that list.prepend()
does not exist due to performance concerns for large lists. For a short list, how do I prepend a value?

- 24,552
- 19
- 101
- 135

- 26,645
- 10
- 56
- 76
8 Answers
The s.insert(0, x)
form is the most common.
Whenever you see it though, it may be time to consider using a collections.deque instead of a list. Prepending to a deque runs in constant time. Prepending to a list runs in linear time.

- 216,523
- 63
- 388
- 485
-
23"Whenever you see it though, it may be time to consider using a collections.deque instead of a list." Why is this? – Mattwmaster58 Feb 15 '20 at 03:18
-
44@MattM. If you insert at the front of a list, python has to move all the other items one space forwards, lists can't "make space at the front". collections.deque (double ended queue) has support for "making space at the front" and is much faster in this case. – fejfo Mar 18 '20 at 14:49
-
11@fejfo, I think that comment should be part of the answer. – zrajm Apr 17 '21 at 14:01
-
2in terms of computation time, is `new_list = [x] + your_list` less efficient than `your_list.insert(x)`? – Charlie Parker Jul 21 '21 at 16:47
-
1@CharlieParker Yes, creating a new list would be less efficient because the all of the object reference counts would have to be updated. Otherwise, the copying workload is similar. – Raymond Hettinger Jul 22 '21 at 02:30
-
If one does have a list as an input to the function, and one converts it to a deque, is that just as inefficient as inserting at the beginning of the list? – Kaizzen May 26 '22 at 05:48
-
That would depend on the implementation, if it does not need to make a copy of the list then it might be faster than inserting – Robin De Schepper Sep 12 '22 at 13:31
This creates a new list with x
prepended to it, rather than modifying an existing list:
new_list = [x] + old_list

- 24,552
- 19
- 101
- 135

- 4,377
- 1
- 16
- 6
-
62As you observe, that isn't prepending to a list. It's creating a new list. Thus it doesn't satisfy the question at all. – Chris Morgan Jun 05 '12 at 06:43
-
238While it doesn't satisfy the question, it rounds it out, and that is the purpose of this website. Appreciate the comment and you are right, but when people search for this, it's helpful to see this. – dave4jr Feb 20 '18 at 16:48
-
5Also, if you want to prepend a list to a list then using insert won't work as expected. but this method does! – gota Aug 29 '18 at 15:55
-
2What's wrong with your_list = [x] + your_list? That wouldn't create a new list would it? – lightbox142 Dec 07 '20 at 02:17
-
2
-
2in terms of computation time, is `new_list = [x] + your_list` less efficient than `your_list.insert(x)`? – Charlie Parker Jul 21 '21 at 16:47
What's the idiomatic syntax for prepending to a short python list?
You don't usually want to repetitively prepend to a list in Python.
If the list is short, and you're not doing it a lot... then ok.
list.insert
The list.insert
can be used this way.
list.insert(0, x)
But this is inefficient, because in Python, a list
is an array of pointers, and Python must now take every pointer in the list and move it down by one to insert the pointer to your object in the first slot, so this is really only efficient for rather short lists, as you ask.
Here's a snippet from the CPython source where this is implemented - and as you can see, we start at the end of the array and move everything down by one for every insertion:
for (i = n; --i >= where; )
items[i+1] = items[i];
If you want a container/list that's efficient at prepending elements, you want a linked list. Python has a doubly linked list, which can insert at the beginning and end quickly - it's called a deque
.
deque.appendleft
A collections.deque
has many of the methods of a list. list.sort
is an exception, making deque
definitively not entirely Liskov substitutable for list
.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
The deque
also has an appendleft
method (as well as popleft
). The deque
is a double-ended queue and a doubly-linked list - no matter the length, it always takes the same amount of time to preprend something. In big O notation, O(1) versus the O(n) time for lists. Here's the usage:
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
Also relevant is the deque's extendleft
method, which iteratively prepends:
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
Note that each element will be prepended one at a time, thus effectively reversing their order.
Performance of list
versus deque
First we setup with some iterative prepending:
import timeit
from collections import deque
def list_insert_0(prepends: int):
l = []
for i in range(prepends):
l.insert(0, i)
def list_slice_insert(prepends):
l = []
for i in range(prepends):
l[:0] = [i] # semantically same as list.insert(0, i)
def list_add(prepends):
l = []
for i in range(prepends):
l = [i] + l # caveat: new list each time
def deque_appendleft(prepends):
d = deque()
for i in range(prepends):
d.appendleft(i) # semantically same as list.insert(0, i)
def deque_extendleft(prepends):
d = deque()
d.extendleft(range(prepends)) # semantically same as deque_appendleft above
And a function for analysis, so that we can fairly compare all operations across a range of usages:
def compare_prepends(n, runs_per_trial):
results = {}
for function in (
list_insert_0, list_slice_insert,
list_add, deque_appendleft, deque_extendleft,
):
shortest_time = min(timeit.repeat(
lambda: function(n), number=runs_per_trial))
results[function.__name__] = shortest_time
ranked_methods = sorted(results.items(), key=lambda kv: kv[1])
for name, duration in ranked_methods:
print(f'{name} took {duration} seconds')
and performance (adjusting the number of runs per trial down to compensate for longer running times of more prepends - repeat
does three trials by default):
compare_prepends(20, 1_000_000)
compare_prepends(100, 100_000)
compare_prepends(500, 100_000)
compare_prepends(2500, 10_000)
>>> compare_prepends(20, 1_000_000)
deque_extendleft took 0.6490256823599339 seconds
deque_appendleft took 1.4702797569334507 seconds
list_insert_0 took 1.9417422469705343 seconds
list_add took 2.7092894352972507 seconds
list_slice_insert took 3.1809083241969347 seconds
>>> compare_prepends(100, 100_000)
deque_extendleft took 0.1177942156791687 seconds
deque_appendleft took 0.5385235995054245 seconds
list_insert_0 took 0.9471780974417925 seconds
list_slice_insert took 1.4850486349314451 seconds
list_add took 2.1660344172269106 seconds
>>> compare_prepends(500, 100_000)
deque_extendleft took 0.7309095915406942 seconds
deque_appendleft took 2.895373275503516 seconds
list_slice_insert took 8.782583676278591 seconds
list_insert_0 took 8.931685039773583 seconds
list_add took 30.113558700308204 seconds
>>> compare_prepends(2500, 10_000)
deque_extendleft took 0.4839253816753626 seconds
deque_appendleft took 1.5615574326366186 seconds
list_slice_insert took 6.712615916505456 seconds
list_insert_0 took 13.894083382561803 seconds
list_add took 72.1727528590709 seconds
The deque is much faster. As the lists get longer, deques perform even better. If you can use deque's extendleft
you'll probably get the best performance that way.
If you must use lists, keep in mind that for small lists, list.insert
works faster, but for larger lists, inserting using slice notation becomes faster.
Don't prepend to lists
Lists were meant to be appended to, not prepended to. If you have a situation where this kind of prepending is a hurting the performace of your code, either switch to a deque or, if you can reverse your semantics and accomplish the same goal, reverse your list and append instead.
In general, avoid prepending to the built-in Python list
object.

- 374,368
- 89
- 403
- 331
-
1in terms of computation time, is `new_list = [x] + your_list` less efficient than `your_list.insert(x)`? – Charlie Parker Jul 21 '21 at 17:13
-
1Yes. They are semantically different - the first one creates two new lists and throws away the short one with just `x`, and the second mutates the original list, in place. In terms of computation, I would expect similar performance for the semantically similar parts - and a larger performance hit on the first for the allocation of space for the new lists. I am usually able to avoid problems with mutability by only appending to lists. And if I need a generic algorithm (for example, from Haskell) that mutates on the beginning of a list, I might reverse it to work from the end. – Russia Must Remove Putin Jul 21 '21 at 18:28
-
`your_list.insert(0, x)` has to move every element of `your_list` up one position, essentially making the same copy that `[x] + your_list` has to make. – chepner Apr 22 '22 at 20:37
If someone finds this question like me, here are my performance tests of proposed methods:
Python 2.7.8
In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop
In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop
In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop
As you can see, insert
and slice assignment are as almost twice as fast than explicit adding and are very close in results. As Raymond Hettinger noted insert
is more common option and I, personally prefer this way to prepend to list.
-
8@Dakkaron I think you're wrong about that. Quite a few sources cite linear complexity for list.insert, eg [this nice table](https://wiki.python.org/moin/TimeComplexity), and implied by the reasonable explanation the questioner linked to. I suspect CPython is re-allocating each element in memory in the list in the first two cases, so all three of these probably have linear complexity. I haven't actually looked at the code or tested it myself though, so sorry if those sources are wrong. Collections.deque.appendleft does have the linear complexity you're talking about. – T.C. Proctor Jul 17 '17 at 21:36
-
1@Dakkaron not true, all of these have equivalent complexity. Although `.insert` and `[0:0] = [0]` work *in-place*, they still have to re-allocate the entire buffer. – juanpa.arrivillaga Feb 15 '19 at 00:58
-
5These benchmarks are bad. The initial list should be created in separate setup step, not part of the timing itself. And the last creates a new list 1000001 long, so comparing with the other two mutating in-place versions is apples and oranges. – wim Jan 30 '20 at 06:54
-
In my opinion, the most elegant and idiomatic way of prepending an element or list to another list, in Python, is using the expansion operator * (also called unpacking operator),
# Initial list
l = [4, 5, 6]
# Modification
l = [1, 2, 3, *l]
Where the resulting list after the modification is [1, 2, 3, 4, 5, 6]
I also like simply combining two lists with the operator +, as shown,
# Prepends [1, 2, 3] to l
l = [1, 2, 3] + l
# Prepends element 42 to l
l = [42] + l
I don't like the other common approach, l.insert(0, value)
, as it requires a magic number. Moreover, insert()
only allows prepending a single element, however the approach above has the same syntax for prepending a single element or multiple elements.

- 2,127
- 23
- 17
-
in terms of computation time, is `new_list = [x] + your_list` less efficient than `your_list.insert(x)`? – Charlie Parker Jul 21 '21 at 17:15
-
1How so? :Smile: The only thing I'll say without the presence of my defense attorney is that "premature optimization is the root of all evil". As stated in the first paragraph of my answer, I am referring to the idiomatic way of concatenating two lists. – jose.angel.jimenez Jul 21 '21 at 17:39
Lets go over 4 methods
- Using insert()
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l.insert(0, 5)
>>> l
[5, 0, 1, 2, 3, 4]
>>>
- Using [] and +
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = [5] + l
>>> l
[5, 0, 1, 2, 3, 4]
>>>
- Using Slicing
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l[:0] = [5]
>>> l
[5, 0, 1, 2, 3, 4]
>>>
- Using collections.deque.appendleft()
>>>
>>> from collections import deque
>>>
>>> l = list(range(5))
>>> l
[0, 1, 2, 3, 4]
>>> l = deque(l)
>>> l.appendleft(5)
>>> l = list(l)
>>> l
[5, 0, 1, 2, 3, 4]
>>>

- 39
- 1
-
1Your answer beautifully summarizes all options but doesn't answer the question asked. Please provide a coherent answer. – Epsi95 Jan 23 '21 at 09:08
-
1As new answer to an old question, you should be providing new insight or information. This answer does not answer the original question, and just repeats the information already available in the other answers. – snakecharmerb Jan 23 '21 at 09:23
-
in terms of computation time, is `new_list = [x] + your_list` less efficient than `your_list.insert(x)`? – Charlie Parker Jul 21 '21 at 17:15
I would have done something quite fast forward in python >= 3.0
list=[0,*list]
It maybe be not the most efficient way, but it's the most Pythonic in my opinion.

- 1,790
- 1
- 24
- 40
For a small list, you can use the insert() method to prepend a value to a list:
my_list = [2, 3, 4]
my_list.insert(0, 1)
However, for large lists, it may be more efficient to use a deque instead of a list:
from collections import deque
my_list = deque([2, 3, 4])
my_list.appendleft(1)
Deques are a data structure that supports efficient prepend and append operations and is generally faster than lists for large data structures.

- 312
- 3
- 10