x = [23, "Hello!", "test", 1.44, True]
y = [1, "1", [1, 2, 3], ["test", False, [True, True, 2, 4]]]Creating lists
A list is a container sequence which, unlike strings, can contain items of arbitrary types. We use square brackets to create a new list (with commas separating the list items):
Indexing and slicing
Indexing and slicing works exactly like in strings. We use square brackets to extract a single or multiple items from a list:
x[0]23
x[-2]1.44
x[1:4]['Hello!', 'test', 1.44]
x[::-1][True, 1.44, 'test', 'Hello!', 23]
Working with lists
Length
The len function returns the number of items in a list:
len(x)5
len(y)4
An empty list has a length of zero:
z = []
len(z)0
Modifying lists
In contrast to strings, lists are mutable. That is, items in a list can be modified after the list has been created. For example:
x[23, 'Hello!', 'test', 1.44, True]
x[1] = 12345 # no problem here
x[23, 12345, 'test', 1.44, True]
Remember that we can assign more than one name to a Python object. For example, we could create a second name y for the list that is currently named x:
y = xIf we modify the list, changes are visible through both names x and y, because the underlying list object is one and the same:
x[1] = "Good bye!"
x[23, 'Good bye!', 'test', 1.44, True]
y[23, 'Good bye!', 'test', 1.44, True]
The following example illustrates five options to create a copy of the list x (or in other words, a new list):
x = [1, 2, 3, 4]
x1 = x.copy()
x2 = list(x)
x3 = x[:]
import copy
x4 = copy.copy(x)
x5 = copy.deepcopy(x)Note that if the list contains mutable objects (such as lists) itself, only copy.deepcopy will create copies from all objects (but this is also the slowest method).
Concatenation
Adding lists with the + operator concatenates their items and creates a new list:
[1, 2, "three"] + ["four", 5, 6.0][1, 2, 'three', 'four', 5, 6.0]
Likewise, the * concatenates list items multiple times:
[1.0, 2, "three"] * 3[1.0, 2, 'three', 1.0, 2, 'three', 1.0, 2, 'three']
List methods
Lists have their own host of methods. Bear in mind that in general, list methods change the given list in place, whereas string methods always create a new string. One of the most frequently used list methods is append, which (as the name implies) appends a new item at the end of the list:
x[1, 2, 3, 4]
x.append(13)
x[1, 2, 3, 4, 13]
Because list methods change the list in place, they do not return anything (or rather, they return None). Therefore, the following code will not work as expected:
x = x.append(13)After this line, x will be None (the return value of append), and the modified list will not be accessible anymore. Therefore, the correct way to append an item to a list is to rely on in-place modification as shown in the previous example.
If we want to append more than one item, we can use the related extend method:
x.extend(["A", "B", "C"])
x[1, 2, 3, 4, 13, 'A', 'B', 'C']
Note that x.append(["A", "B", "C"]) also works, but produces a different result:
x.append(["A", "B", "C"])
x[1, 2, 3, 4, 13, 'A', 'B', 'C', ['A', 'B', 'C']]
The del keyword or the pop method both remove items from a list. For example, the following statement removes two items at the given indexes (1 and 2):
del x[1:3]
x[1, 4, 13, 'A', 'B', 'C', ['A', 'B', 'C']]
Similarly, this is how to remove the last item using pop:
x.pop(-1)['A', 'B', 'C']
x[1, 4, 13, 'A', 'B', 'C']
Note that pop returns the removed item and changes the list in place (del does not return anything).
The remove method removes items by value (instead of by index). For example, x.remove(13) removes the first item in the list which is equal to 13:
x.remove(13)
x[1, 4, 'A', 'B', 'C']
Finally, the sort method sorts a list in place if this is possible. This means that all items should be of the same type, otherwise sorting will result in an error.
x.sort()--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[25], line 1 ----> 1 x.sort() TypeError: '<' not supported between instances of 'str' and 'int'
To demonstrate this, let’s create a new list h consisting of only numbers and sort it:
h = [6, 9, 23, 1, -78, 44]
h.sort()
h[-78, 1, 6, 9, 23, 44]
Iterating over lists
The in keyword checks whether a specific value is contained in a list:
x = [1, 2, 3, 4, 5]
2 in xTrue
7 in xFalse
Iteration with a for-loop also works as expected:
for item in x:
print(item)1
2
3
4
5
Tuples
Tuples are basically immutable lists. We will not go into more detail why tuples are useful, but suffice it to say that we should prefer a tuple instead of a list whenever we do not want to change its items. For example, instead of storing the latitude and longitude of a given location in a list, a tuple might be more reasonable (because the coordinates of a given location will not change).
The syntax for creating a tuple is similar to creating a list, except that it doesn’t use square brackets. Strictly speaking, listing items separated by commas defines a tuple, but sometimes parentheses are required and/or improve readability:
t = 23, "Hello!", "test", 1.44, True
t(23, 'Hello!', 'test', 1.44, True)
We cannot modify tuples because they are immutable:
t[1]'Hello!'
t[1] = 12345--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[32], line 1 ----> 1 t[1] = 12345 TypeError: 'tuple' object does not support item assignment
List comprehensions
There is another neat way to construct a list in Python: list comprehensions. These do not introduce any new functionality (everything can be accomplished without list comprehensions), but this so-called syntactic sugar makes some list assignments shorter to write and/or easier to read.
Consider the following example, where we want to create a list containing all squares from numbers 1 to 10. We already know how to do this with a for-loop:
squares = []
for n in range(1, 11):
squares.append(n**2)The resulting list is:
squares[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
The alternative list comprehension is much more compact and looks as follows:
squares = [n**2 for n in range(1, 11)]
squares[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In general, a list comprehension is surrounded by square brackets (to denote that a list will be constructed). Inside the brackets, the first expression defines the individual items that go into the new list (n**2 in our example). After that, something very similar to a for-loop iterates over some sequence (some iterable) to generate the individual items (in our case, n takes on values from range(1, 11)).
Here’s another example of a list comprehension, which multiplies each item in a (numeric) list by 2:
numbers = [-4, -2, 0, 2, 4]
numbers2 = [n * 2 for n in numbers]
numbers2[-8, -4, 0, 4, 8]
Every time we want to apply some operation to each individual item in a list, a list comprehension might be the way to go. Another example is taking the absolute value of each item in a list:
numbers_abs = [abs(x) for x in numbers]
numbers_abs[4, 2, 0, 2, 4]
Remember that all list comprehensions can be written with a regular loop and the append method. We can also include a condition in the list comprehension, which will include an item in the new list only if the condition is True. This is useful for filtering values as shown in the following example, where we filter all values greater than or equal to zero:
[x for x in numbers if x >= 0][0, 2, 4]
List comprehensions can even be nested:
lst = [(x - 1, y - 2) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
lst[(0, 1), (0, 2), (1, 1), (1, -1), (1, 2), (2, -1), (2, 2)]
This is a pretty complex list comprehension, and in this case, the traditional way might be more readable:
lst = [] # start with an empty list
for x in [1, 2, 3]:
for y in [3, 1, 4]:
if x != y:
lst.append((x - 1, y - 2))The results are exactly the same (observe how the individual for and if statements correspond to each other in both list assignments).
Let’s finish up this topic with a slightly less complex list comprehension just to see another example:
freshfruit = [' banana', ' loganberry ', 'passion fruit ']
[weapon.strip().upper() + "!" for weapon in freshfruit] # creates a new list['BANANA!', 'LOGANBERRY!', 'PASSION FRUIT!']
Exercises
Write a function
histogramwhich accepts a list of numbers as its input argument. The function should convert the argument to a simple (vertical) histogram as follows: Each item of the list defines a row in the histogram, the length of which is defined by the value in the list. By default, the histogram should consist of*characters (but it should be possible to change this character with a second argument).Here are two examples that demonstrate the behavior of the function:
>>> histogram([1, 8, 5, 17, 14, 9, 2]) * ******** ***** ***************** ************** ********* ** >>> histogram([1, 8, 5, 17, 2], char="-") - -------- ----- ----------------- --Use the
printfunction to print the histogram row by row. Repeating a string might be useful, for example"*" * 8is"********".Define a function
sum_of_squareswhich takes a list of numbers and returns the sum of all squared items (one number). Note that the built-in functionsumcomputes the sum of a list of numbers.Create a list
numbersconsisting of the 25 integers from 1 to 25. Based on this list, generate the following five new lists:squarescontaining the squared numbersevenscontaining the even numbersoddscontaining the odd numbersrootscontaining the square roots of the numberslogscontaining the natural logarithms of the numbers
For the last two lists, use the functions
sqrtandlogfrom themathmodule (first,import mathand then use the functions asmath.sqrtandmath.log, respectively).Find out what is wrong with the following code:
x = [1, 2, 3, 4] x = x.append(5)
This document is licensed under the CC BY-NC-SA 4.0 by Clemens Brunner.