Python 101: Learning About Lists

Lists are a fundamental data type in the Python programming language. A list is a mutable sequence that is typically a collection of homogeneous items. Mutable means that you can change a list after its creation. You will frequently see lists that contain other lists. These are known as nested lists. You will also see lists that contain all manner of other data types, such as dictionaries, tuples or objects.

Let’s find out how you can create a list!

Creating Lists

There are several ways to create a list. You may construct a list in any of the following ways:

  • Using a pair of square brackets with nothing inside creates an empty list: []
  • Using square brackets with comma-separated items: [1, 2, 3]
  • Using a list comprehension: [x for x in iterable]
  • Using the list() function: list(iterable)

An iterable is a sequence, a container that supports iteration or an iterator object. Lists themselves are sequences as are strings.

Let’s look at a few examples of creating a list so you can see it in action:

>>> my_list = [1, 2, 3]
>>> my_list
[1, 2, 3]

This first example is pretty straight-forward. Here you create a list with 3 numbers in it. Then you print it out to verify that it contains what you think it should.

The next way to create a list is by using Python’s built-in list() function:

>>> list_of_strings = list('abc')
>>> list_of_strings
['a', 'b', 'c']

In this case, you pass a string of three letters to the list() function. It automatically iterates over the characters in the string to create a list of three string, where each string is a single character.

The last example to look at is how to create empty lists:

>>> empty_list = []
>>> empty_list
[]
>>> another_empty_list = list()
>>> another_empty_list
[]

The quickest way to create an empty list is by using the square brackets without putting anything inside them. The second easiest way is to call list() without any arguments. The nice thing about using list() in general is that you can use it to cast a compatible data type to a list, as you did with the string, “abc”, in the example earlier.

List Methods

A Python list has several methods that you can call. Here is a listing of the methods you can use with a list:

  • append()
  • clear()
  • copy()
  • count()
  • extend()
  • index()
  • insert()
  • pop()
  • remove()
  • reverse()
  • sort()

Most of these will be covered in the following sections. Let’s talk about the ones that aren’t covered in a specific section first.

You can use count() to count the number of instances of the object that you passed in.

Here is an example:

>>> my_list = list('abcc')
>>> my_list.count('a')
1
>>> my_list.count('c')
2

This is a simple way to count the number of occurrences of an item in a list.

The index() method is useful for finding the first instance of an item in a list:

>>> my_list = list('abcc')
>>> my_list.index('c')
2
>>> my_list.index('a')
0

Python lists are zero-indexed, so “a” is in position 0, “b” is at position 1, etc.

You can use the reverse() method to reverse a list in-place:

>>> my_list = list('abcc')
>>> my_list.reverse()
>>> my_list
['c', 'c', 'b', 'a']

Note that the reverse() method returns None. What that means is that if you try to assign the reversed list to a new variable, you may end up with something unexpected:

>>> x = my_list.reverse()
>>> print(x)
None

Here you end up with None instead of the reversed list. That is what in-place means. The original list is reversed, but the reverse() method itself doesn’t return anything.

Now let’s find out what you can do with the other list methods!

Adding to a List

There are three list methods that you can use to add to a list. They are as follows:

  • append()
  • extend()
  • insert()

The append() method will add an item to the end of a pre-existing list:

>>> my_list = list('abcc')
>>> my_list
['a', 'b', 'c', 'c']
>>> my_list.append(1)
>>> my_list
['a', 'b', 'c', 'c', 1]

First you create a list that is made up of four one-character strings. Then you append an integer to the end of the list. Now the list should have 5 items in it with the 1 on the end.

You can use Python’s built-in len() function to check the number of items in a list:

>>> len(my_list)
5

So this tells you that you do in fact have five items in the list. But what if you wanted to add an element somewhere other than the end of the list?

You can use insert() for that:

>>> my_list.insert(0, 'first')
>>> my_list
['first', 'a', 'b', 'c', 'c', 1]

The insert() method takes two arguments:

  • The position at which to insert
  • The item to insert

In the code above, you tell Python that you want to insert the string, “first”, into the 0 position, which is the first position in the list.

There are two other ways to add items to a list. You can add an iterable to a list using extend():

>>> my_list = [1, 2, 3]
>>> other_list = [4, 5, 6]
>>> my_list.extend(other_list)
>>> my_list
[1, 2, 3, 4, 5, 6]

Here you create two lists. Then you use my_list‘s extend() method to add the items in other_list to my_list. extend() will iterate over the items in the passed in list and add each of them to the list.

You can also combine lists using concatenation:

>>> my_list = [1, 2, 3]
>>> other_list = [4, 5, 6]
>>> combined = my_list + other_list
>>> combined
[1, 2, 3, 4, 5, 6]

In this case, you create two lists and then combine them using Python’s + operator.

You can also use += with Python lists:

>>> my_list = [1, 2, 3]
>>> other_list = [4, 5, 6]
>>> my_list += other_list
>>> my_list
[1, 2, 3, 4, 5, 6]

This is a somewhat simpler way to combine the two lists.

Now let’s learn how to access and change elements within a list.

Accessing and Changing List Elements

Lists are made to be worked with. You will need to learn how to access individual elements as well as how to change them.

Let’s start by learning how to access an item:

>>> my_list = [1, 2, 3]
>>> my_list[0]
1
>>> my_list[2]
3

To access an item in a list, you need to use square braces and pass in the index of the item that you wish to access. In the example above, you access the first and third elements.

Lists also support accessing items in reverse by using negative values:

>>> my_list[-1]
3

This example demonstrates that when you pass in -1, you get the last item in the list returned. Try using some other values and see if you can get the first item using negative indexing.

If you try to use an index that does not exist in the list, you will get an IndexError:

>>> my_list[-5]
Traceback (most recent call last):
Python Shell, prompt 41, line 1
builtins.IndexError: list index out of range

Now let’s learn about removing items!

Deleting From a List

Deleting items from a list is pretty straight-forward. There are 4 primary methods of removing items from a list:

  • clear()
  • pop()
  • remove()
  • del

You can use clear() to remove everything from the list. Let’s see how that works:

>>> my_list = [1, 2, 3]
>>> my_list.clear()
>>> my_list
[]

After calling clear(), the list is now empty. This can be useful when you have finished working on the items in the list and you need to start over from scratch. Of course, you could also do this instead of clear():

>> my_list = []

This will create a new empty list. If it is important for you to always use the same object, then using clear() would be better. If that does not matter, then setting it to an empty list will work well too.

If you would rather remove individual items, then you should check out pop() or remove(). Let’s start with pop():

>>> my_list = [1, 2, 3]
>>> my_list.pop()
3
>>> my_list
[1, 2]

You can pass an index to pop() to remove an item and return it. Or you can call pop() without an argument like in the example above and it will default to removing the last item in the list and returning it. pop() is the most flexible way of removing items from a list.

If the list is empty or you pass in an index that does not exist, pop() will throw an exception:

>>> my_list.pop(10)
Traceback (most recent call last):
  Python Shell, prompt 50, line 1
builtins.IndexError: pop index out of range

Now let’s take a look at how remove() works:

>>> my_list = [1, 2, 3]
>>> my_list.remove(2)
>>> my_list
[1, 3]

remove() will delete the first instance of the passed in item. So in this case, you tell the list to remove the first occurrence of the number 2.

If you tell remove() to delete an item that is not in the list, you will receive an exception:

>>> my_list.remove(4)
Traceback (most recent call last):
  Python Shell, prompt 51, line 1
builtins.ValueError: list.remove(x): x not in list

You can also use Python’s built-in del keyword to delete items from a list:

>>> my_list = [1, 2, 3]
>>> del my_list[1]
>>> my_list
[1, 3]

You will receive an error if you try to remove an index that does not exist:

>>> my_list = [1, 2, 3]
>>> del my_list[6]
Traceback (most recent call last):
  Python Shell, prompt 296, line 1
builtins.IndexError: list assignment index out of range

Now let’s learn about sorting a list!

Sorting a List

Lists in Python can be sorted. You can use the built-in sort() method to sort a list in-place or you can use Python’s sorted() function.

Let’s create a list and try sorting it:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> my_list.sort()
>>> my_list
[1, 2, 4, 9, 10, 23]

Here you create a list with 6 integers in a pretty random order. To sort the list, you call its sort() method, which will sort it in-place. What that means is that sort() does not return anything.

A common misconception with Python is that if you call sort(), you can assign the result to a variable, like this:

>>> sorted_list = my_list.sort()
>>> print(sorted_list)
None

However, when you do that, you will see that sort() doesn’t actually return a sorted list. It always returns None.

Fortunately you can use Python’s built-in sorted() method for this too:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> sorted_list = sorted(my_list)
>>> sorted_list
[1, 2, 4, 9, 10, 23]

If you use sorted(), it will return a new list, sorted ascending by default. The sorted() function will also allow you to sort by a specified key and you can tell it to sort ascending or descending by setting its reversed flag.

Let’s sort this list in descending order instead:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> sorted_list = sorted(my_list, reverse=True)
>>> sorted_list
[23, 10, 9, 4, 2, 1]

When you have a more complicated data structure, such as a nested list or a dictionary, you can use sorted() to sort in special ways, such as by key or by value.

List Slicing

Python lists support the idea of slicing. Slicing a list is done by using square brackets and entering a start and stop value. For example, if you had my_list[1:3], you would be saying that you want to create a new list with the element starting at index one through 3 but not including index 3.

Here is an example:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> my_list[1:3]
[10, 2]

This slice returns index 1 (10) and index 2 (2) as a new list.

You can also use negative values to slice:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> my_list[-2:]
[23, 9]

In this example, you didn’t specify an end value. That means you want to start at the second to last item in the list, 23, and take it to the end of the list.

Let’s try another example where you specify only the end index:

>>> my_list = [4, 10, 2, 1, 23, 9]
>>> my_list[:3]
[4, 10, 2]

In this example, you want to grab all the values starting at index 0 up to but not including index 3.

Copying a List

Occasionally you will want to copy a list. One simple way to copy your list is to use the copy method:

>>> my_list = [1, 2, 3]
>>> new_list = my_list.copy()
>>> new_list
[1, 2, 3]

This successfully creates a new list and assigns it to the variable, new_list.

However note that when you do this, you are creating what is known as a “shallow copy”. What that means is that if you were to have objects in your list, they can be changed and it will affect both lists. For example, if you had a dictionary in your list and the dictionary was modified, both lists will change, which may not be what you want.

You can also copy a list by using this funny syntax:

>>> my_list = [1, 2, 3]
>>> new_list = my_list[:]
>>> new_list
[1, 2, 3]

This example is telling Python to create a slice from the 0 (first) element to the last, which in effect is the copy of the whole list.

You could also use Python’s list() function to copy a list:

>>> my_list = [1, 2, 3]
>>> new_list = list(my_list)
>>> new_list
[1, 2, 3]

No matter which method you choose though, whether it by [:], copy() or list(), all three will do a shallow copy. If you run into weird issues where changing one list affects the copied list, then you should use deepcopy method from the copy module instead.

Wrapping Up

In this article, you learned all about Python’s wonderful list data type. You will be using lists extensively when you are programming in Python. Here you learned how to create lists, edit them and remove items from them. You learned how to clear a list completely. You discovered how to sort a list as well as how to slice a list. Finally, you learned all about copying lists and the pitfalls that can happen when you do so.