Python | Which is faster to initialize lists?

Python is a very flexible language where a single task can be performed in a number of ways, for example initializing lists can be performed in many ways. However there are subtle differences in these seemingly similar methods. Python which is popular for its simplicity and readability is equally infamous for being slow compared to C++ or Java. The ‘for’ loop is especially known to be slow whereas methods like map() and filter() known to be faster because they are written in C. Knowing the better and faster way to initialize lists might give you a slight edge in competitive programming.

The following are some of the ways to initialize lists(we create lists of size 1000 and initialize with zeros) in Python.

Using a for loop and append()
We create an empty an list and run a for loop for n times using the append() method to add elements to the list.



arr = []
for i in range(1000):
    arr.append(0)

Using a while loop with a counter variable
This is similar to the above method. However we use while loop instead.

arr = []
i = 0
while(i<1000):
    arr.append(0)

Using list comprehensions
It consists of square brackets containing an expression followed by a for clause and further followed by an optional if clause. The expression can be any type of object that we want to put in the list. Since we are initializing the list with zeros, our expression will just be 0.

arr = [0 for i in range(1000)]

Using the * operator
The * operator can be used as [object]*n where n is the no of elements in the array.

arr = [0]*1000

Lets look at the time taken by each of them. We will calculate the average time taken by each of these methods to initialize an array of 10000 elements over 500 times.

filter_none

edit
close

play_arrow

link
brightness_4
code

# import time module to calculate times
import time
  
# initialise lists to save the times
forLoopTime = []
whileLoopTime = []
listComprehensionTime = []
starOperatorTime = []
  
# repeat the process for 500 times
# and calculate average of times taken.
for k in range(500): 
  
    # start time
    start = time.time()
    # declare empty list
    a = []
    # run a for loop for 10000 times
    for i in range(10000):
        a.append(0)
    # stop time
    stop = time.time()
    forLoopTime.append(stop-start)
  
    # start time
    start = time.time()
    # declare an empty list
    a = []
    i = 0
    # run a for loop 10000 times
    while(i<10000):
        a.append(0)
        i+= 1
    stop = time.time()
    whileLoopTime.append(stop-start)
  
    start = time.time()
    # list comprehension to initialize list
    a = [0 for i in range(10000)] 
    stop = time.time()
    listComprehensionTime.append(stop-start)
  
  
    start = time.time()
    # using the * operator
    a = [0]*10000 
    stop = time.time()
    starOperatorTime.append(stop-start)
  
  
  
print("Average time taken by for loop: " + str(sum(forLoopTime)/100))
print("Average time taken by while loop: " + str(sum(whileLoopTime)/100))
print("Average time taken by list comprehensions: " + str(sum(listComprehensionTime)/100))
print("Average time taken by * operator: " + str(sum(starOperatorTime)/100))    

chevron_right


Output

Average time taken by for loop: 0.012432687282562256
Average time taken by while loop: 0.017907898426055908
Average time taken by list comprehensions: 0.0034629487991333007
Average time taken by * operator: 0.0001951146125793457

Note: The times will vary based on the platform where this code is executed. These times are just for studying the relative performance of these methods of initializing.

  • As it can be seen, for and while loops take almost the same time with for loop having a slight edge.
  • List comprehensions perform much better than for and while loops with the former being around 3-5 times faster. Another example of this difference can be seen when we try to create a list of numbers from 1-1000. Using list comprehensions is much better than using append().
    a = [i for  i in range(1, 1001)]
  • Using the * operator is way faster than the remaining methods and this is the way you should be initializing lists

However one drawback of using the * operator is while declaring 2d arrays. Using this operator would create shallow lists i.e only one list object would be created and all the indices would refer to this object. This might create unwanted complications. Hence using list comprehensions is a safer way to create 2d lists.


Using * operator would create shallow lists
arr = [[0]*no_of_cols]*no_of_rows

Using list comprehensions is better for 2d arrays
arr = [[0 for i in range(no_of_cols)] for j in range(no_of_rows)]



My Personal Notes arrow_drop_up


If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.