Lists in Python Demystified (Part 1)



A quick tour on how Lists work in the awesome Python Language (Part 1)

Lists are cool and homogeneous

In Python, lists are commonplace. They're used pretty much in every Python codebase around.

So what are they?

Lists are, what we call, mutable sequences. Despite them being very similar to Tuples, they do not have the same immutable drawbacks.

Lists can be created using the list() constructor.

Lists are used to store collections of data. Let's see an example:

empty_list = [] # creates an empty list
another_empty_list = list() # creates another empty list
type(empty_list) # returns <class 'list'>
empty_list == another_empty_list # returns True

Initialising a list with values

A list can also be initialised with default values placed between the square brackets or by invoking the list() constructor.

even_numbers = [ 2, 4, 6, 8, 10 ]
odd_numbers = [ 1, 3, 5, 7, 9 ]
sequence_list = list([3, 4, 5, 6]) # new list with default values being assigned

Accessing individual items from a list

Items can be accessed using the indexing/slicing notation. If you try to access an item which is not present in the list, an IndexError will be raised.

numbers = [ 1, 10, 100, 1000, 10000]
numbers[0] # first element in the list, returns 1
numbers[1] # second element in the list, returns 10
numbers[-1] # last element in the list, return 10000
numbers[100] # returns IndexError: list index out of range

Adding new items to a list

The list.append() method allows an item to be added into the result set.

a = []
a.append(1) # adds a new value to the 'a' set
a.append(4) # a is now [1, 2, 3, 4]

Removing items from a list

The list.remove() method allows an item to be removed from the result set.

a = [1, 2, 3 ,4]
a.remove(4) # removes the value 4 from the 'a' set, a is now [1, 2, 3]

Membership testing in lists

The in operator is used to demonstrate membership testing in Python and it's quite central when using lists to check for items being present in a specific list. Using the in operator will always return a boolean result.

Here's an example:

a = [1, 2, 3, 4]
5 in a # returns False
3 in a # returns True

Counting items in a list

We can use Python's in-built len() method to count the total number of items in a list.

a = [1, 2, 3, 4]
len(a) # returns 4

Counting the exact occurences of an item in a list

One can make use of the list.count() method to count the number of occurences of an item in a list.

a = [1, 2, 3, 4, 5, 1]
a.count(1) # returns 2, there are 2 instances of the number 1 being present in the list.

Extending items in a list

The list.extend() method allows a list to extend or concatenate its result set to another list/sequence.

a = [1, 2, 3]
b = [3, 4, 5]
a.extend(b) # a is now [1,2,3,3,4,5], b is still [3,4,5]

Pay attention to the fact that lists are mutable and hence, the silent behaviour of the list 'a' being extended.

Another easy way is to use the overloaded operator + to achieve the same effect.

a + b # returns [1,2,3,3,4,5]

Reversing items in a list

The list.reverse() method allows the items in a list to be reversed.

a = [1, 2, 3]
students = ["Tom", "Andy", "Sean"]
a.reverse() # a is now [3, 2, 1]
students.reverse() # students is now ['Sean', 'Andy', 'Tom']

There's another way of reversing a list using the indexing/slicing notation.

The format to do is in the form: list[start:end:step]

numbers = [1, 2, 3]
numbers[::-1] # returns [3, 2, 1]

Sorting items in a list

The list.sort() and Python's built-in sorted() method allows sorting in a very simple way.

The list.sort() method allows in-place sorting, which means that the original list is modified straight away.

The sorted() method creates a new sorted list from an iterable and works for other types other than lists.

a = [100, 20, 84, 72, 8, 22, 34]
sorted(a) # returns [8, 20, 22, 34, 72, 84, 100], a is left unchanged
a.sort() # returns [8, 20, 22, 34, 72, 84, 100], a modified in-place

students = ["Mark", "Tom", "John", "Oz"]
sorted(students) # returns ['John', 'Mark', 'Oz', 'Tom'], students is left unchanged
students.sort() # fruits is now ['John', 'Mark', 'Oz', 'Tom'] , students modified in-place

We have a slight problem when we have to sort items which in turn have both lower and uppercase characters.

fruits = ['apples', 'Bananas', 'oranges', 'Pears', 'Apples']
sorted(fruits) # returns ['Apples', 'Bananas', 'Pears', 'apples', 'oranges']
fruits.sort() # fruits is now ['Apples', 'Bananas', 'Pears', 'apples', 'oranges'] WTH??

As we can see, the lowercase apples and oranges did not get properly sorted to our liking.

To solve this issue, we can make use of a key function.

sorted(fruits, key=lambda v: v.upper()) # returns ['apples', 'Apples', 'Bananas', 'oranges', 'Pears']
fruits.sort(key=lambda v: v.upper()) # fruits is now ['apples', 'Apples', 'Bananas', 'oranges', 'Pears']

Awesome, isn't it?? Using the lambda function defined in the key allowed us to specify in which order the values will be returned.

Now what if we wanted the uppercase values first? Hmm..let's see how we can solve this one:

sorted(fruits, key=lambda v: (v.upper(), v[0].islower())) # returns ['Apples', 'apples', 'Bananas', 'oranges', 'Pears']
fruits.sort(key=lambda v: (v.upper(), v[0].islower())) # fruits is now ['Apples', 'apples', 'Bananas', 'oranges', 'Pears']

We haven't talked much about lambdas here but we'll get to this in a future lecture. But, we now have the ability to sort values whether it's in lower or upper case. Cool!

Shallow copying

A shallow copy or also known as field-by-field copy is normally referred to as a bitwise copy of an object. Shallow copies are considered simple and cheap.

To make a shallow copy of the list, we can use the following:

another_list = numbers[:] # shallow copy
yet_another_list = list(numbers) # another way of doing shallow copying.

We can also make use of Python's built-in copy module.

import copy
yet_another_shallow_list = copy.copy(numbers) # another way of shallow copy using Python's copy library

Deep Copying

A deep copy, unlike a shallow copy, copies all the fields and any de-referenced objects linked to that object in memory. Deep copies have a complicated object graph and considered expensive.

To make a deep copy of the list, we can make use of Python's built-in copy module again. We use the deepcopy() method to achieve this functionality.

import copy
deep_copy_list = copy.deepcopy(numbers) # this makes a deep copy using Python's copy library

Do you use lists in Python or want to suggest an improvement to this article? Please share it with us by leaving a reply below.

Stay tuned for Part 2 where we will talk more about Lists.

Continue to

About the Author

Alvin Luchmun
Alvin Luchmun is a freelance developer, trainer and co-founder at and currently lives in London. Alvin is passionate about anything tech/biz related but is also a firm believer in agile clean code, he loves preaching about code to fellow humanoids!.

Leave a comment