Best and/or fastest way to create lists in python
Question: In python, as far as I know, there are at least 3 to 4 ways to create and
initialize lists of a given size:

**Simple loop with`append`:**

    
    
    my_list = []
    for i in range(50):
        my_list.append(0)
    

**Simple loop with`+=`:**

    
    
    my_list = []
    for i in range(50):
        my_list += [0]
    

**List comprehension:**

    
    
    my_list = [0 for i in range(50)]
    

**List and integer multiplication:**

    
    
    my_list = [0] * 50
    

In these examples I don't think there would be any performance difference
given that the lists have only 50 elements, but what if I need a list of a
million elements? Would the use of `xrange` make any improvement? Which is the
preferred/fastest way to create and initialize lists in python?


Answer: Let's run some time tests* with
[`timeit.timeit`](http://docs.python.org/2/library/timeit.html#timeit.timeit):

    
    
    >>> from timeit import timeit
    >>>
    >>> # Test 1
    >>> test = """
    ... my_list = []
    ... for i in xrange(50):
    ...     my_list.append(0)
    ... """
    >>> timeit(test)
    22.384258893239178
    >>>
    >>> # Test 2
    >>> test = """
    ... my_list = []
    ... for i in xrange(50):
    ...     my_list += [0]
    ... """
    >>> timeit(test)
    34.494779364416445
    >>>
    >>> # Test 3
    >>> test = "my_list = [0 for i in xrange(50)]"
    >>> timeit(test)
    9.490926919482774
    >>>
    >>> # Test 4
    >>> test = "my_list = [0] * 50"
    >>> timeit(test)
    1.5340533503559755
    >>>
    

As you can see above, the last method is the fastest by far.

* * *

However, it should _only_ be used with immutable items (such as integers).
This is because it will create a list with references to the same item.

Below is a demonstration:

    
    
    >>> lst = [[]] * 3
    >>> lst
    [[], [], []]
    >>> # The ids of the items in `lst` are the same
    >>> id(lst[0])
    28734408
    >>> id(lst[1])
    28734408
    >>> id(lst[2])
    28734408
    >>>
    

This behavior is very often undesirable and can lead to bugs in the code.

If you have mutable items (such as lists), then you should use the still very
fast list comprehension:

    
    
    >>> lst = [[] for _ in xrange(3)]
    >>> lst
    [[], [], []]
    >>> # The ids of the items in `lst` are different
    >>> id(lst[0])
    28796688
    >>> id(lst[1])
    28796648
    >>> id(lst[2])
    28736168
    >>>
    

* * *

*Note: In all of the tests, I replaced `range` with `xrange`. Since the latter returns an iterator, it should always be faster than the former.

