Python Lists (for absolute beginners)

Let’s face it, unless you’re coding a “hello world” program, you’ll definitely need to use lists in your projects.

In this article, I am going to teach you what a python list is, how to use it, and what operations you can apply on it.

What is a list?

A list is simply an ordered collection of items.

Let’s stop here for a second and elaborate on what I just said.

Before we start, let me remind you that everything in python is an object. This means that when you create a list, you’re essentially creating a python object of a specific type (list).

In that sense, creating a list is not very different from creating, let’s say, an integer. However, what’s cool about a list is that it’s an object that contains other objects.

I will use the words item, element, and object interchangeably. They all mean the same thing.

So now, what do I mean by ordered?

As I said, a list is a collection of items, but it’s not just a bag that you randomly put items in and scatter them around. Each item in a list has an order or an index that uniquely identifies this item.

Lists, Tuples, and Strings are all data types that, in python, are called sequence data typesAll of them are containers of items and all of them have items that are ordered.

For instance, consider the string “hello”. “h” would be the first item in the string and its index is 0. “e” is the second item with an index of 1 and so on and so forth.

Now without further ado, let’s get our hands dirty and do some coding. And before we can do anything with lists, we need to be able to create one.

How to create a list?

Creating a list in python is very simple.

You can create an empty list L like this

# This is a python list L that has no items stored
L = []

Lists in python are declared using square brackets. What goes inside these brackets is a comma separated list of items. If no items are provided, an empty list is created.

Similar to creating variables of other types, python first allocates some memory for the list object and assigns the variable L to refer to it.

Now let’s create a list and initialize it with some elements. You can do that by adding the list items within the square brackets.

For instance if you want to initialize your list with the string “apple“, the string “banana“, and the integer 1, this is what you will need to do.

L = ["apple", "banana", 1]

hmm interesting. So our list has a string object at index 0, a string object at index 1, and an integer object at index 2. So the items the list contains are of different types. I mean…is this even legal? Can we store items of different types in a list or do they have to be of the same type?

What type of elements can I store in a python list?

Python lists are extremely flexible.

Lists essentially store python objects and because everything in python is an object, then you can basically store anything in a list.

Each item in a python list can be of any data type. In the example above, we created a list with two strings: apple and banana, and one integer: and that was fine. There is no such limitation that a list can only store items of the same data type.

And yes, since a list is a python object, a list can be an item in another list! Take a look at this example.

L = [["red apple", "green apple"], "banana", 10]
print(L[0]) #output = ["red apple", "green apple"]

here we have a list L where the first item is another list [“red apple”, “green apple”]

Not only that python lists are extremely flexible regarding the data type of items they can store, but they’re also very flexible regarding their size.

You can freely grow and shrink a python list as much as you want without having to declare its size in advance.

How to read the items of a list?

Earlier I talked about the fact that a list is an ordered collection of items. I also mentioned that each item within a list has an index that uniquely identifies this item.

That said, you can easily read a particular item in a list given its index. So if you know index of the item that you would like to access, then accessing the element is very straightforward, just put the index of the item in square brackets.

Let’s try to access a list item by its index in an interactive shell:

>>> L = ["apple", "banana", 1]
>>> L[0] #get the first element in L
'apple'
>>> L[1] #get the second element in L
'banana'
>>> L[2]
1

Seems pretty straightforward, right?

What’s also cool about python is that it allows for negative indices such that the element with index -1 is the last element in the list.

The element with index -2 is the second to last and so on and so forth.

This can really come in handy if you want to refer to the last element of a list without having to know the length of the list first.

>>> L = ["apple", "banana", 1]
>>> L[-1]
1
>>> L[-2]
'banana'
>>> L[-3]
'apple'

So far, we were able to read a single item from a list. But what if we need to read a subset of the list. For example, let’s say I want to read the first three elements of a list in the form of another list. This is where slicing comes in handy.

A slice is essentially a sub-list that can be identified by a starting index and an end index. The slice contains all the elements starting from the start index and ending (but not including) the end index.

Let me show you an example

>>> L = ["apple", "banana", "peach", "strawberry", 1, 2, 3]
>>> L[0:2]
['apple', 'banana']
>>> L[2:-1]
['peach', 'strawberry', 1, 2]

The start-index is the index before the colon. The end-index is the one after the colon.

If you don’t put a start-index, it is 0 by default. If you don’t put an end-index, it is the length of the list by default.

>>> L[:3]
['apple', 'banana', 'peach']
>>> L[2:]
['peach', 'strawberry', 1, 2, 3]

Now let’s talk about how you could read every element in a list, one at a time.

Iterating over the items of a list

Most of the time, you’ll need to iterate over all the items of a list, one at a time. Let’s say we have a list of integers L and we need print all the integers in the list. One way to do that is to iterate over all the integers in the list, one by one, and print the integer.

You can use a for loop to do that

L = [1, 3, 5, 7]
for x in L:
  print(x)
# output:
1
3
5
7

When you use a for loop to iterate over a list as in the example above, in each iteration of the loop, x will store the value of one of the items in the list, one at a time, ordered by their index.

In the first iteration, x stores the value of the item at index 0.

In the second iteration, x stores the value of the item at index 1 and so on and so forth.

You can also iterate over a list with a for loop to detect if an item exists in a list or not. For example, if your list represents a grocery list and you want to know if “apple” is a member of the list, you can iterate over the items one by one and check if the item is actually “apple”.

But once again, python provides you with an easier way to do that.

How to detect if an item exists in a list? (The ‘in’ operator)

You will often times need to check if an item exists in a particular list.

Python provides a very useful operator that allows you to quickly test if an object is a member of a list or not. This is the in operator.

In fact, the in operator works for any python sequence types (strings, tuples, and lists). It takes two operands, the object you are testing for, and the list. It returns ‘true’ if the object is in the list and ‘false’ otherwise.

You can also use the not in operator to check the absence of a specific object (the return value is ‘true’ if the object doesn’t exist)

Let’s take an example.

>>> L = ["apple", "banana", 1]
>>> "apple" in L
True
>>> "strawberry" in L
False
>>> 1 not in L
False
>>> "peach" not in L
True

So far, we learnt how to create a list, read an item from a list, iterate over all the items in a list, and check if an item exists in a list. But what if we want to modify or write new items to the list?

How to modify and write elements to a list?

Unlike python strings, lists are mutable.

But what do I mean by mutable exactly?

A mutable data type means you can change or modify the contents of an object of that type. Whereas an immutable data type will not allow you to change its contents.

If you want to dive deeper, Megha Mohan wrote a very good article that talks about mutable and immutable objects in python.

Let’s take look at the most popular immutable data type in python: strings

We are going to create a string “hwllo world” with a typo and then try to modify the second character in the string to be an “e” instead of “w”.

To do this in python, we run the following code:

>>> s = "hwllo world"
>>> s[1]
'w'
>>> s[1] = 'e' #attempt to assign 'e' to s[1]
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'str' object does not support item assignment

Notice that strings are also indexed and you can access a specific character in the string by its index (for example: s[1] = ‘w’).

Notice also that when I tried to modify the second character (index = 1) to be an ‘e’ instead of ‘w’, I got an error. That’s because strings are immutable. You can’t modify or change the content of a string object after it’s been created.

How about this code though?

>>> s = "hwllo world"
>>> s
'hwllo world'
>>> s = "hello world"
>>> s
'hello world

You must be thinking, Karim, you said immutable objects can’t be modified and yet ‘s’ was modified to be “hello world” in this code. What’s the deal?

This is actually a very important question and is a reason for confusion among many beginners.

In fact, the python object that held the string value “hwllo world” was NEVER modified. In other words to be clearer, the block of memory that stored the object that represents the string value “hwllo world” never changed, not one bit.

What really happened is that python created a totally brand new string object (in a new memory location) with the string value “hello world” and then re-assigned the variable name ‘s’ to point to this newly created object. The older object was never touched. Now let’s turn our focus to lists which is a mutable data type.

Lists will oblige to any sort of modification or change.

Let’s try to modify the items of a list and see if it works.

>>> L = ["apple", "banana", 1]
>>> L[1]
'banana'
>>> L[1] = "strawberry"
>>> L
['apple', 'strawberry', 1]

Sweet! it worked. No error messages.

You can also iterate over all the items of a list and modify them one by one.

Let’s take as an example an integer list [1, 3, 5, 7] and let’s say we want to multiply each item in the list by 2. We can do that in various ways but I will take this chance to also teach you about the enumerate built-in function in the process.

Remember that previously, we were able to iterate over a list and get the value of each item, one at a time. But sometimes, we also want to get the index along with the value. enumerate is a built-in function that makes it easy to do so.

enumerate iterates over a list and returns both the index and the value of each item. This is useful for the problem we are trying to solve. Let’s look at the code.

L = [1, 3, 5, 7]
for idx, item in enumerate(L):
  L[idx] = item * 2
# L = [2, 6, 10, 14]

Besides modifying existing list items, you can also write new list items to an existing list.  I am going to talk about two functions that achieve just that: append and extend

First: Appending to a list

You can use the append function to add an item to the end of the list. As we said earlier, because of the flexibility of python lists, this item can be of any type.

Let’s take an example:

>>> L = ["apple", "banana", 1]
>>> L.append(20)
>>> L
['apple', 'banana', 1, 20]

Second: Extending a list

Similar to appendextend is another method that can be used to add items to a list. So what is the difference?

The major difference is that extend basically extends the list with another list (or any iterable for that matter) while append adds only one item/object to the list.

Let’s study this code and discuss what’s going on.

>>> L1 = ["apple", "banana", 1]
>>> L2 = ["apple", "banana", 1]
>>> X = [5, "strawberry"]
>>> L1.append(X)
>>> L2.extend(X)
>>> L1
['apple', 'banana', 1, [5, 'strawberry']]
>>> L2
['apple', 'banana', 1, 5, 'strawberry']

interesting! Let’s talk about what just happened.

We created two lists L1 and L2 with identical items [“apple”, “banana”, 1]. We also created another list X with items [5, “strawberry”]

Can you see what happened when we appended X to L1?

Python appended X as a single element to L1. After appending, the total length of L1 is 4 and the last element of L1 happens to be a list (the one we just appended).

That’s not the case when we use extend though. Extend looks into each item of X and adds each item separately to L2. In other words, extend essentially appends each item of X while append just appends X.

The distinction can be confusing for beginners, so make sure you completely internalize and fully understand the difference.

How to delete items from a list? (three ways)

Now let’s talk about deleting items from a python list.

As usual there are multiple ways to do that but I am going to discuss three.

First: Delete an element by its index

If you know the index of the element you want to delete, then you can easily remove this element using the del statement.

>>> L = ["apple", "banana", 1]
>>> del L[1]
>>> L
['apple', 1]

It’s that simple. But what if we don’t know the index but we know the value that we want to remove? What if we want to remove “banana” from the list but we don’t know the index? well, one solution is that you could possibly find the index of “banana” first, and then remove it using its index. But there is a better way…

Second: Delete an element by its value

 

To remove an item by its value, you can use the remove  method. Let’s see how

>>> L = ["apple", "banana", 1]
>>> L.remove("banana")
>>> L
['apple', 1]

Pretty straightforward!

So what happens if we have more than one “banana” element in the list. Well, let’s try it out and see what happens.

>>> L = ["apple", "banana", 1, "banana"]
>>> L.remove("banana")
>>> L
['apple', 1, 'banana']

Interesting! It seems like the remove function only removes the first occurrence of the element that matches the input value.

If you try to use remove and there is no element in the list that matches the provided value, you will get an error. Try it out!

Third: Deleting an element by index and getting back the removed value

In some scenarios, what you really need to do is to get an item out of the list and remove the item at the same time.

Of course since you have the index you can read the item first and then remove it. Two steps total. Can python help us get them down to one?

Of course!

Python provides a very handy way to do that using the pop function. The pop function can be used as follows:

 

>>> L = ["apple", "banana", 1]
>>> x = L.pop(1)
>>> L
['apple', 1]
>>> x
'banana'

First notice that the pop method takes as an input the index of the item that needs to be removed, and returns that item. So in our example, the item with index ‘1’ was removed and stored in x.

Inspecting L reveals that “banana” was removed from the list. Inspecting reveals that the string “banana” is stored in variable x.

Important: You are not permitted to remove items from a list while iterating over the list. The python interpreter will throw an error.

List Comprehension

List comprehensions are ummm interesting. They were one of the things that freaked me out when I started with python.

The reason is, as far as I know, list comprehensions don’t exist in other traditional programming languages. I came from C and Java before I started Python and there is nothing in these languages that looks even remotely close to list comprehension in python.

But don’t worry, they’re very simple once you get used to.

Before we discuss what a list comprehension is, let’s set the stage by discussing a very common piece of code that you’ll find yourself frequently writing. You often times want to iterate over all the items of some list, process each item in some manner, and append the resulting item to a new list. Assume you have a list L, you want to double the value of each item in the list L and put the result in a new list doubles.

The code for such task would look something like this.

L = [1, 2, 3, 4, 5]
doubles = []
for n in L:
  doubles.append(2 * n) # doubles = [2, 4, 6, 8, 10]

Because this operation is very common, python allows you a very handy way to perform the above operation in ONE line of code

doubles = [2 * n for n in L] # doubles = [2, 4, 6, 8, 10]

pretty cool, right? So this can be generalized to any sort of processing you can do over the items of the list. Indeed, a very powerful and concise way to describe your code. But again as I said earlier, it takes some time getting used to :). Especially if you are coming from other languages.

Not only that, you can even use an if statement in list comprehension to append only if the if condition is true. Let’s take an example

L = [1, 2, 3, 4, 5]
doubles = [2 * n for n in L if (n % 2 == 0)] # doubles = [4, 8]

Here we double the list item and append it to doubles only if the if condition is true (in the example, the if condition is true only for even numbers). That’s why the resulting doubles list will be [4, 8]

Learning Python?

If you are a beginner, then I highly recommend this book.

No longer a beginner?

Then you are ready for this book to get to the next level (It’s my favorite).

Related Articles

 

 

2018-11-19T01:17:16+00:00 By |

Leave A Comment