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, 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
0
as the first element.- Lines 6 and 8
Index from the back using negative indices starting with
-1
as the last element.- Lines 10 and 12
Slice with
[m:n]
, wherem
is the inclusive start point andn
is 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
-1
reverses 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
y
list to the end of the list withappend
, but the elementy
list.- Line 16
appends the elements of the
y
list 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 valuei
from it?If you have a nested list
ll
, how can you get a copynll
of this list in which you can change the elements without changing the contents ofll
?
Make sure that the
my_collection
object is a list before you try to append data to it.