How can you insert an element at a given index in a given list? Python’s
insert() method is your friend.
This tutorial shows you everything you need to know to help you master an essential method of the most fundamental container data type in the Python programming language.
Definition and Usage:
list.insert(i, element) method adds an element
element to an existing
list at position
i. All elements
j>i will be moved by one index position to the right.
Here’s a short example:
>>> lst = [1, 2, 3, 4] >>> lst.insert(3, 99) >>> lst [1, 2, 3, 99, 4]
In the first line of the example, you create the list
lst. You then insert the integer element 99 at position 3 of the list. The result is the list with five elements
[1, 2, 3, 99, 4].
You can call this method on each list object in Python. Here’s the syntax:
|Integer value representing the position before you want to insert an element|
|Object you want to insert into the list.|
Now you know the basics. Let’s deepen your understanding with a short code puzzle—can you solve it?
# Puzzle # Puzzle created by Finxter Lee lst = [1, 3, 4, 5, 6, 7, 8] lst.insert(1, 2) print(lst) # What's the output of this code snippet?
You can check out the solution on the Finxter app.
To help you fully understand the ins and outs of the
insert() method, let’s dive into a few more examples.
>>> lst = [1, 2, 3] >>> lst.insert(0, 99) >>> lst [99, 1, 2, 3] >>> lst.insert(-1, 42) >>> lst [99, 1, 2, 42, 3] >>> lst.insert(100, 0) >>> lst [99, 1, 2, 42, 3, 0]
An interesting case is the second one where you use a negative index in the
Here’s your free PDF cheat sheet showing you all Python list methods on one simple page. Click the image to download the high-resolution PDF file, print it, and post it to your office wall:
Python List insert() Negative Index
You can use a negative index in the
lst.insert(index, element) method. With a negative index you count backwards, starting from the right. In other words, the index
-1 stands for the rightmost element in the list. The
insert() method inserts the element right in front of the index position. Thus, you get the following behavior where the element is inserted to the second last position:
>>> lst = ["Ann", "Bob", "Alice"] >>> lst.insert(-1, "Liz") >>> lst ['Ann', 'Bob', 'Liz', 'Alice']
What happens if you count further, i.e., -2, -3, or even -99? Let’s check:
>>> lst.insert(-2, "Sam") >>> lst ['Ann', 'Bob', 'Sam', 'Liz', 'Alice']
… and …
>>> lst.insert(-3, "Bob") >>> lst ['Ann', 'Bob', 'Bob', 'Sam', 'Liz', 'Alice']
… and …
>>> lst.insert(-99, "Hans") >>> lst ['Hans', 'Ann', 'Bob', 'Bob', 'Sam', 'Liz', 'Alice']
So you can see that every integer index is allowed! If you overshoot (e.g. -99), it will simply insert at the beginning of the list.
Python List insert() At Beginning
insert() method allows you to add an element at the beginning of a list. Simply use the index 0 in the call
lst.insert(0, element) to add element to the beginning of the
Here’s an example:
>>> lst = [1, 2, 3] >>> lst.insert(0, 99) >>> lst [99, 1, 2, 3]
insert(i, x) method inserts an element
x at position
i in the list. This way, you can insert an element to each position in the list—even at the first position. Note that if you insert an element at the first position, each subsequent element will be moved by one position. In other words, element
i will move to position
Python List insert() At End
Okay, you can insert an element at every position in the list—just use the first argument to define the insertion index. Consequently, you can “insert” an element at the end of a list by defining an index that’s greater or equal the size of the list. Remember,
insert(index, element) inserts
element before the element that’s currently at position
index. So if you define an index that’s at least the size of the list, you’ll insert the element at the end of the list:
>>> lst = [1, 2, 3, 4, 5, 6] >>> lst.insert(6, 99) >>> lst [1, 2, 3, 4, 5, 6, 99] >>> lst.insert(100000, 42) >>> lst [1, 2, 3, 4, 5, 6, 99, 42]
No matter your concrete choice of the index argument, as long as it’s larger or equal the current size of the list, your element will be inserted at the end of the list.
However, this doesn’t make a lot of sense considering that you can use the
append(element) method which adds an element at the end of the list—and is highly efficient (and readable). Read more about the
append() method at my detailed blog article.
Here’s an example adding the same elements 99 and 42 to the end of the list:
>>> lst = [1, 2, 3, 4, 5, 6] >>> lst.append(99) >>> lst.append(42) >>> lst [1, 2, 3, 4, 5, 6, 99, 42]
In Python, there are usually a lot of ways to accomplish the same thing. Using the
append() method to add an element to the end of the list is the better way!
Python insert() into Sorted List
How to insert an element into a sorted list (ascending order) and keep the list sorted?
The naive approach is to go over all elements, from first to last, as long as the element to be inserted is still smaller than the current element in the list. As soon as it’s larger, you go back one position and insert it there.
However, the computational complexity of the naive sorted insert algorithm is bad because you need up to n operations to insert an element into a list of n elements.
If you’re interested in the right way of doing it, you can use binary search and the
list.insert(i,x) method to insert element
x at position
i in the list. Here’s the code for the binary search algorithm in Python:
def binary_search(lst, value): lo, hi = 0, len(lst)-1 while lo <= hi: mid = (lo + hi) // 2 if lst[mid] < value: lo = mid + 1 elif value < lst[mid]: hi = mid - 1 else: return mid return -1 l = [3, 6, 14, 16, 33, 55, 56, 89] x = 56 print(binary_search(l,x)) # 6 (the index of the found element)
Don’t worry if the code looks a bit complicated!
Python List insert() Multiple Elements
How can you insert multiple elements into a list? Just call the
insert() method multiple times—once for each element to be inserted! But be careful: you must reverse the order of the elements to be inserted first if you keep the insert position constant. Here’s what I mean:
>>> lst = [1, 2, 3, 4] >>> insert = [42, 99] >>> insert.reverse() >>> for el in insert: lst.insert(2, el) >>> lst [1, 2, 42, 99, 3, 4]
You want to insert elements 42 and 99 at position 2 of the list
lst, in that order. If you’d just iterate over both elements, you’d first insert element 42 before index 2. Now, element 42 obtains the position 2 in the list. Next, you’d insert element 99 before position 2. Now, element 99 obtains position 2 in the list. So basically, you’ve reversed the original order of the elements to be inserted. Therefore, you have to call the
reverse() method first before inserting the elements into the list.
There’s really no better alternative. Of course, you could use list concatenation but that is not as efficient because you’d create a new list rather than modify an existing list:
>>> lst = [1, 2, 3, 4] >>> insert = [42, 99] >>> lst = lst[:2] + insert + lst[2:] >>> lst [1, 2, 42, 99, 3, 4]
This may be more readable but it’s not as efficient because list concatenation creates a new list each time it’s used. If you need to refresh your basic Python slicing skills (e.g. in the operation
lst[:2]), check out this detailed blog tutorial.
Python List insert() Complexity
Time Complexity: The
insert() method has constant time complexity O(1) no matter the number of elements in the list. The reason is that Python lists are implemented with variable-length array lists so accessing a certain position is fast. Also inserting an element into the array list is fast because you only have to modify the pointers of the preceding and following elements in the list.
Python List insert() vs append()
The difference between the
append() and the
insert() method is the following:
append(x)method adds new element
xto the end of the list, and
insert(i, x)method adds new element
iin the list. It shifts all subsequent elements one position to the right.
Here’s an example showing both
insert() methods in action:
>>> l = [1, 2, 3] >>> l.append(99) >>> l [1, 2, 3, 99] >>> l.insert(2, 42) >>> l [1, 2, 42, 3, 99]
Both methods help you add new elements to the list. But you may ask:
Which is faster, append() or insert()?
All things being equal, the
append() method is significantly faster than the
Here’s a small script that shows that the
append() method has a huge performance advantage over the
insert() method when creating a list with 100,000 elements.
import time l1 =  l2 =  t1 = time.time() for i in range(100000): l1.append(i) t2 = time.time() for i in range(100000): l2.insert(0,i) t3 = time.time() print("append(): " + str(t2 - t1) + " seconds") print("insert(): " + str(t3 - t2) + " seconds") # OUTPUT: # append(): 0.015607357025146484 seconds # insert(): 1.5420396327972412 seconds
The experiments were performed on my notebook with an Intel(R) Core(TM) i7-8565U 1.8GHz processor (with Turbo Boost up to 4.6 GHz) and 8 GB of RAM.
Alternatives: Python List append() vs extend()
Instead of inserting an element, you can also add a single element to the end of the list using the
append() method or even adding multiple elements to the end of the list using the
What’s the difference?
I shot a small video explaining the difference and which method is faster, too:
list.append(x) adds element
x to the end of the
list.extend(iter) adds all elements in
iter to the end of the
The difference between
extend() is that the former adds only one element and the latter adds a collection of elements to the list.
You can see this in the following example:
>>> l =  >>> l.append(1) >>> l.append(2) >>> l [1, 2] >>> l.extend([3, 4, 5]) >>> l [1, 2, 3, 4, 5]
In the code, you first add integer elements 1 and 2 to the list using two calls to the
append() method. Then, you use the extend method to add the three elements 3, 4, and 5 in a single call of the
Which method is faster — extend() vs append()?
To answer this question, I’ve written a short script that tests the runtime performance of creating large lists of increasing sizes using the
extend() and the
Our thesis is that the
extend() method should be faster for larger list sizes because Python can append elements to a list in a batch rather than by calling the same method again and again.
I used my notebook with an Intel(R) Core(TM) i7-8565U 1.8GHz processor (with Turbo Boost up to 4.6 GHz) and 8 GB of RAM.
Then, I created 100 lists with both methods,
append(), with sizes ranging from 10,000 elements to 1,000,000 elements. As elements, I simply incremented integer numbers by one starting from 0.
Here’s the code I used to measure and plot the results: which method is faster—
import time def list_by_append(n): '''Creates a list & appends n elements''' lst =  for i in range(n): lst.append(n) return lst def list_by_extend(n): '''Creates a list & extends it with n elements''' lst =  lst.extend(range(n)) return lst # Compare runtime of both methods list_sizes = [i * 10000 for i in range(100)] append_runtimes =  extend_runtimes =  for size in list_sizes: # Get time stamps time_0 = time.time() list_by_append(size) time_1 = time.time() list_by_extend(size) time_2 = time.time() # Calculate runtimes append_runtimes.append((size, time_1 - time_0)) extend_runtimes.append((size, time_2 - time_1)) # Plot everything import matplotlib.pyplot as plt import numpy as np append_runtimes = np.array(append_runtimes) extend_runtimes = np.array(extend_runtimes) print(append_runtimes) print(extend_runtimes) plt.plot(append_runtimes[:,0], append_runtimes[:,1], label='append()') plt.plot(extend_runtimes[:,0], extend_runtimes[:,1], label='extend()') plt.xlabel('list size') plt.ylabel('runtime (seconds)') plt.legend() plt.savefig('append_vs_extend.jpg') plt.show()
The code consists of three high-level parts:
- In the first part of the code, you define two functions
list_by_extend(n)that take as input argument an integer list size
nand create lists of successively increasing integer elements using the
- In the second part of the code, you compare the runtime of both functions using 100 different values for the list size
- In the third part of the code, you plot everything using the Python matplotlib library.
Here’s the resulting plot that compares the runtime of the two methods append() vs extend(). On the x axis, you can see the list size from 0 to 1,000,000 elements. On the y axis, you can see the runtime in seconds needed to execute the respective functions.
The resulting plot shows that both methods are extremely fast for a few tens of thousands of elements. In fact, they are so fast that the
time() function of the time module cannot capture the elapsed time.
But as you increase the size of the lists to hundreds of thousands of elements, the
extend() method starts to win:
For large lists with one million elements, the runtime of the
extend() method is 60% faster than the runtime of the
The reason is the already mentioned batching of individual append operations.
However, the effect only plays out for very large lists. For small lists, you can choose either method. Well, for clarity of your code, it would still make sense to prefer
append() if you need to add a bunch of elements rather than only a single element.
Python List insert() Returns None
The return value of the
insert() method is
None. The return value of the
insert() method is not a modified list with the added elements. Assuming this is a common source of mistakes.
Here’s such an error where the coder wrongly assumed this:
>>> lst = [1, 2].insert(1, 99) >>> lst Traceback (most recent call last): File "<pyshell#16>", line 1, in <module> lst TypeError: 'NoneType' object is not subscriptable
It doesn’t make sense to assign the result of the
insert() method to another variable—because it’s always
None. Instead, the
insert() method changes a list object without creating (and returning) a new list.
Here’s the correct version of the same code:
>>> lst = [1, 2] >>> lst.insert(1, 99) >>> lst 99
Now, you change the list object itself by calling the
insert() method on it. You through away the
None return value because it’s not needed.
Python List insert() Return New List
If you use the
lst.insert(index, element) operation, you add the
element to the existing list
lst. But what if you want to create a new list where all elements were added?
The answer is simply to use the list concatenation operation
lst[:index] + [element] + lst[index:] which creates a new list each time it is used. The original list
lst will not be affected by the list concatenation operation.
Here’s an example that shows that the
insert() method only modifies an existing list:
>>> lst_1 = [1, 2, 3] >>> lst_2 = lst_1.insert(1, 42) >>> lst_1 [1, 42, 2, 3] >>> lst_2 None
And here’s the example that shows how to create a new list inserting element 42 at index 2:
>>> lst_1 = [1, 2, 3] >>> lst_2 = lst_1[:1] +  + lst_1[1:] >>> lst_1 [1, 2, 3] >>> lst_2 [1, 42, 2, 3]
By using the list concatenation operation, you can create a new list rather than inserting the element into an existing list.
Python List insert() Thread Safe
Do you have a multiple threads that access your list at the same time? Then you need to be sure that the list operations (such as
insert()) are actually thread safe.
In other words: can you call the
insert() operation in two threads on the same list at the same time? (And can you be sure that the result is meaningful?)
The answer is yes (if you use the cPython implementation). The reason is Python’s global interpreter lock that ensures that a thread that’s currently working on it’s code will first finish its current basic Python operation as defined by the cPython implementation. Only if it terminates with this operation will the next thread be able to access the computational resource. This is ensured with a sophisticated locking scheme by the cPython implementation.
The only thing you need to know is that each basic operation in the cPython implementation is atomic. It’s executed wholly and at once before any other thread has the chance to run on the same virtual engine. Therefore, there are no race conditions. An example for such a race condition would be the following: the first thread reads a value from the list, the second threads overwrites the value, and the first thread overwrites the value again invalidating the second thread’s operation.
All cPython operations are thread-safe. But if you combine those operations into higher-level functions, those are not generally thread safe as they consist of many (possibly interleaving) operations.
Where to Go From Here?
list.insert(index, element) method inserts an
element to the end of the
list before the given
You’ve learned the ins and outs of this important Python list method.
If you keep struggling with those basic Python commands and you feel stuck in your learning progress, I’ve got something for you: Python One-Liners (Amazon Link).
In the book, I’ll give you a thorough overview of critical computer science topics such as machine learning, regular expression, data science, NumPy, and Python basics—all in a single line of Python code!
OFFICIAL BOOK DESCRIPTION: Python One-Liners will show readers how to perform useful tasks with one line of Python code. Following a brief Python refresher, the book covers essential advanced topics like slicing, list comprehension, broadcasting, lambda functions, algorithms, regular expressions, neural networks, logistic regression and more. Each of the 50 book sections introduces a problem to solve, walks the reader through the skills necessary to solve that problem, then provides a concise one-liner Python solution with a detailed explanation.
While working as a researcher in distributed systems, Dr. Christian Mayer found his love for teaching computer science students.
To help students reach higher levels of Python success, he founded the programming education website Finxter.com. He’s author of the popular programming book Python One-Liners (NoStarch 2020), coauthor of the Coffee Break Python series of self-published books, computer science enthusiast, freelancer, and owner of one of the top 10 largest Python blogs worldwide.
His passions are writing, reading, and coding. But his greatest passion is to serve aspiring coders through Finxter and help them to boost their skills. You can join his free email academy here.