Lists¶
A list in Python is similar to an array in Java or C: an ordered collection of objects. However, unlike lists in many other languages, Python lists can contain different types of elements; a list element can be any Python object, including Strings, Tuples, Lists, Dictionaries, Functions, ../../save-data/files and any kind of Numbers. You create a list by enclosing no elements or elements separated by commas in square brackets, like this:
1 []
2 [1]
3 [1, "2.", 3.0, ["4a", "4b"], (5.1, 5.2)]
Tip
I recommend that you do not use the ctypes.Array type
available in Python, but if numerical calculations require it, consider
NumPy, which is described in our
Python for Data Science tutorial.
Indices¶
Elements can be extracted from a Python list using a notation similar to array
indexing in C, starting with 0; asking for element 0 will return the
first element of the list, asking for element 1 will return the second
element, and so on. Here are a few examples:
1>>> x = [1, "2.", 3.0, ["4a", "4b"], (5.1, 5.2)]
2>>> x[0]
3'1'
4>>> x[1]
5'2.'
A list can be indexed from the front or the back. You can also refer to a sub-segment of a list by using the slice notation:
6>>> x[-1]
7(5.1, 5.2)
8>>> x[-2]
9['4a', '4b']
10>>> x[1:-1]
11['2.', 3.0, ['4a', '4b']]
12>>> x[0:3]
13[1, '2.', 3.0]
14>>> x[:3]
15[1, '2.', 3.0]
16>>> x[-4:-1]
17['2.', 3.0, ['4a', '4b']]
18>>> x[-4:]
19['2.', 3.0, ['4a', '4b'], (5.1, 5.2)]
- Lines 2 and 4
Index from the beginning using positive indices starting with
0as the first element.- Lines 6 and 8
Index from the back using negative indices starting with
-1as the last element.- Lines 10 and 12
Slice with
[m:n], wheremis the inclusive start point andnis the exclusive end point.- Lines 14, 16 and 18
A
[:n]slice starts at the beginning and an[m:]slice goes to the end of a list.
Slices also allow a step-by-step selection between the start and end indices.
The default value for an unspecified stride is 1, which takes every element
from a sequence between the indices. With a stride of 2, every second
element is taken and so on:
1>>> x[0:3:2]
2[1, [3.1, 3.2, 3.3]]
3>>> x[::2]
4[1, [3.1, 3.2, 3.3]]
5>>> x[1::2]
6['secondly', (5.1, 5.2)]
The stride value can also be negative. A -1 stride means counting from right
to left:
1>>> x[3:0:-2]
2[(5.1, 5.2), 'secondly']
3>>> x[::-2]
4[(5.1, 5.2), 'secondly']
5>>> x[::-1]
6[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1]
- Line 1
To use a negative increment, the start slice should be larger than the end slice.
- Line 3
The exception is if you omit the start and end indices.
- Line 5
A stride of
-1reverses the order.Tip
To reverse the order, however,
list.reverse()should be easier to read than a stride of-1, see also list.reverse().
See also
Changing lists¶
You can use this notation to add, remove and replace elements in a list or to get an element or a new list that is a slice of it, for example:
1>>> x = [1, "2.", 3.0, ["4a", "4b"], (5.1, 5.2)]
2>>> x[1] = "secondly"
3>>> x
4[1, 'secondly', 3.0, ['4a', '4b'], (5.1, 5.2)]
5>>> x[5:] = [6, 7]
6>>> x
7[1, 'secondly', 3.0, ['4a', '4b'], (5.1, 5.2), 6, 7]
8>>> x[:0] = [-1, 0]
9>>> x
10[-1, 0, 1, 'secondly', 3.0, ['4a', '4b'], (5.1, 5.2), 6, 7]
11>>> x[2:3] = []
12>>> x
13[-1, 0, 'secondly', 3.0, ['4a', '4b'], (5.1, 5.2), 6, 7]
- Line 2
replaces the second element of the list.
- Line 5
adds elements at the end of the list.
- Line 8
adds elements at the beginning of the list.
- Line 11
removes elements from the list.
Some functions of the slice notation can also be executed with special operations, which improves the readability of the code:
1>>> x.reverse()
2>>> x
3[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1]
You can also use the built-in functions (len(), max() and
min()), some operators (in, not in, + and *),
the del statement and the list methods (append, count, extend,
index, insert, pop, remove, reverse, sort and sum) for lists:
1>>> len(x)
24
3>>> x[len(x) :] = [0, -1]
4>>> x
5[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1]
6>>> x.append(-2)
7>>> x
8[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1, -2]
9>>> y = [-3, -4, -5]
10>>> x.append(y)
11>>> x
12[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1, -2, [-3, -4, -5]]
13>>> x[7:8] = []
14>>> x
15[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1, -2]
16>>> x.extend(y)
17>>> x
18[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1, -2, -3, -4, -5]
19>>> x + [-6, -7]
20[(5.1, 5.2), [3.1, 3.2, 3.3], 'secondly', 1, 0, -1, -2, -3, -4, -5, -6, -7]
21>>> x.reverse()
22>>> x
23[-5, -4, -3, -2, -1, 0, 1, 'secondly', [3.1, 3.2, 3.3], (5.1, 5.2)]
- Line 1
shows the number of list elements.
- Line 3
appends a new list to the end of the list.
- Line 6
appends a new element to the end of the list with
append.- Line 10
appends not the elements of the
ylist to the end of the list withappend, but the elementylist.- Line 16
appends the elements of the
ylist withextend.- Line 19
The operators
+and*each create a new list, whereby the original list remains unchanged.- Line 21
The methods of a list are called using the attribute notation for the list itself:
LIST.METHOD(ARGUMENTS).
List operations¶
Sorting lists¶
Lists can be sorted using the built-in Python sort method
list.sort():
>>> x = [5, 3, -3, 3.1, 0, 1]
>>> x.sort()
>>> x
[-3, 0, 1, 3, 3.1, 5]
With this method, sorting is performed on the spot, meaning that the list to be sorted is changed. If you want the original list to remain unchanged, you have two options:
You can use the built-in function
sorted(), which is described in more detail later.You can create a copy of the list and sort the copy:
>>> x = [5, 3, -3, 3.1, 0, 1] >>> y = x[:] >>> y.sort() >>> y [-3, 0, 1, 3, 3.1, 5] >>> x [5, 3, -3, 3.1, 0, 1]
Strings and lists of lists can also be sorted:
>>> hipy_list = ["Say", "hi", "to", "all", "Pythonistas", "!"]
>>> hipy_list.sort()
>>> hipy_list
['!', 'Pythonistas', 'Say', 'all', 'hi', 'to']
>>> ll = [[5.1, 5.2], [4.0, 5.0], [4.0, 3.0], [3.3, 3.2, 3.1]]
>>> ll.sort()
>>> ll
[[3.3, 3.2, 3.1], [4.0, 3.0], [4.0, 5.0], [5.1, 5.2]]
When comparing complex objects, the sub-lists are first sorted by the first element and then by the second element in ascending order.
list.sort() can also sort in reverse order with reverse=True.
A separate key function can also be used to determine how the elements of a
list are to be sorted.
However, the standard key method used by list.sort() requires that
all elements in the list are of comparable type. In a list that contains both
numbers and strings, an Exception is therefore thrown:
>>> x
[-5, -4, -3, -2, -1, 0, 1, 'secondly', [3.1, 3.2, 3.3], (5.1, 5.2)]
>>> x.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'str' and 'int'
User-defined sorting¶
Note
You must be able to define Functions for user-defined sorting. The processing of Strings will also be covered in more detail later.
Python usually sorts words lexicographically – upper case before lower case. However, we want to sort a list of words by the number of characters in each word in ascending order instead:
>>> def ascending_number_chars(string):
... return len(string)
...
>>> hipy_list = ["Say", "hi", "to", "all", "Pythonistas", "!"]
>>> new_list = hipy_list[:]
>>> hipy_list.sort()
>>> hipy_list
['!', 'Pythonistas', 'Say', 'all', 'hi', 'to']
>>> new_list.sort(key=ascending_number_chars)
>>> new_list
['!', 'hi', 'to', 'Say', 'all', 'Pythonistas']
The sorted function¶
Lists have an inbuilt method for sorting themselves list.sort().
However, other iterables in Python, such as the keys of Dictionaries, do not
have a sorting method. However, Python offers the built-in
sorted() function for this purpose, which returns a sorted list
from any iterable. sorted() uses the same
Parameters key and reverse as the
list.sort() method:
>>> x
[5, 3, -3, 3.1, 0, 1]
>>> y = sorted(x)
>>> y
[-3, 0, 1, 3, 3.1, 5]
>>> z = sorted(x, reverse=True)
>>> z
[5, 3.1, 3, 1, 0, -3]
List membership¶
The in and not in, which return a Boolean value, make it easy to check whether a value is contained in a list.
List concatenation¶
The + operator can be used to create a list from two existing lists, whereby
the initial lists remain unchanged:
>>> x = [3, -3, 0, 1]
>>> y = [3.1]
>>> z = x + y
>>> z
[3, -3, 0, 1, 3.1]
List initialisation¶
You can use the * operator to create a list of a certain size and certain
values. This is a common method for working with lists whose size is known in
advance and which do not cause any memory reallocation overhead. You should
therefore prefer append in such cases in order to enlarge the list at the
start of the programme:
>>> x = [None] * 4
>>> x
[None, None, None, None]
The operator for list multiplications * repeats the copying of the
elements of a list the specified number and merges all copies into a new list. A
list with a single instance of None is usually used for list
multiplication, but the list can be anything:
>>> initial_list = [[1, 2, 3, 4]]
>>> arr = initial_list * 4
>>> arr
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
Minimum or maximum of a list¶
You can use max() and min() to find the largest and smallest
element of a list. You will probably use max() and min() mainly for
numeric lists, but you can also use them for lists
with arbitrary elements; however, if the comparison of these types does not make
sense, this will result in an error:
>>> x = [5, 3, -3, 3.1, 0, 1]
>>> max(x)
5
>>> hipy_list = ["Say", "hi", "to", "all", "Pythonistas", "!"]
>>> max(hipy_list)
'to'
>>> max(x + hipy_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'int'
When comparing complex objects, the sub-lists are first analysed according to the first element and then according to the second element (and so on).
>>> ll = [[1.0, 1.1], [1.0, 1.1, 1.2], [0.9, 1.3]]
>>> max(ll)
[1.0, 1.1, 1.2]
Search in a list¶
If you want to know where a value can be found in a list, you can use the
index method. It searches a list for a list element with a specific value
and returns the position of this list element:
1>>> x = [5, 3, 3.0, -3, 3.1, 0, 1]
2>>> x.index(3)
31
4>>> x.index(3.0)
51
6>>> x.index(5.0)
70
8>>> x.index(6)
9Traceback (most recent call last):
10 File "<stdin>", line 1, in <module>
11ValueError: 6 is not in list
- Line 8–11
Attempting to find the position of an element that is not in the list results in an error. This can be avoided by testing the list with the in or not-in list operators before using
index.
Matches in lists¶
count also searches a list for a specific value, but returns the number of
occurrences in the list and not the position:
>>> x = [5, 3, 3.0, -3, 3.1, 0, 1]
>>> x.count(3)
2
>>> x.count(5)
1
>>> x.count(6)
0
Nested lists and deepcopy¶
Lists can be nested, for example to display two-dimensional matrices. The elements of these matrices can be referenced using two-dimensional indices:
>>> ll = [[5.1, 5.2], [4.0, 5.0], [4.0, 3.0], [3.3, 3.2]]
>>> ll[0]
[5.1, 5.2]
>>> ll[0][1]
5.2
As expected, this mechanism can be transferred to more dimensions:
>>> sub = [0]
>>> sup = [sub, 1]
>>> sup
[[0], 1]
>>> sub[0] = 1
>>> sup
[[1], 1]
>>> sup[0][0] = 2
>>> sub
[2]
>>> sup
[[2], 1]
However, if sub is set to a different list, the connection between sub
and sup is interrupted:
>>> sub = [3]
>>> sup
[[2], 1]
You can get a copy of a list by creating a full slice (x[:]) or by using
+ or * (for example, x + [] or x * 1). All three create a
so-called flat copy of the list, which is probably what you want in most cases.
However, if your list contains other lists that are nested within it, you may
want to create a deep copy. You can do this with the copy.deepcopy()
function of the copy module:
>>> shallow = sup[:]
>>> shallow
[[2], 1]
The shallow copy does not copy the elements of the list but only refers to
the original elements. Changing one of these elements affects both shallow and sup:
>>> shallow[1] = 2
>>> shallow
[[2], 2]
>>> sup
[[2], 1]
>>> shallow[0][0] = 0
>>> sup
[[0], 1]
However, deepcopy is independent of the original list and no change to it
has any effect on the original list:
>>> import copy
>>> deep = copy.deepcopy(sup)
>>> deep
[[0], 1]
>>> deep[0][0] = 1
>>> deep
[[1], 1]
>>> sup
[[0], 1]
Checks¶
What does
len()return for each of the following cases:[3][][[1, [2, 3], 4], "5 6"]
How would you use
len()and slices to determine the second half of a list if you don’t know how long it is?How could you move the last two entries of a list to the beginning without changing the order of the two?
Which of the following cases triggers an exception?
min(["1", "2", "3"])max([1, 2, "3"])[1,2,3].count("1")
If you have a list
l, how can you remove a certain valueifrom it?If you have a nested list
ll, how can you get a copynllof this list in which you can change the elements without changing the contents ofll?Make sure that the
my_collectionobject is a list before you try to append data to it.