Tutorial 41 50
Tutorial 41 50
Now that you are about to write longer, more complex pieces of Python, it is a good time to talk about coding style. Most
languages can be written (or more concise, formatted) in different styles; some are more readable than others. Making it
easy for others to read your code is always a good idea, and adopting a nice coding style helps tremendously for that.
For Python, PEP 8 has emerged as the style guide that most projects adhere to; it promotes a very readable and eye-
pleasing coding style. Every Python developer should read it at some point; here are the most important points extracted
for you:
• Use 4-space indentation, and no tabs.
4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation
(easier to read). Tabs introduce confusion, and are best left out.
• Wrap lines so that they don’t exceed 79 characters.
This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.
• Use blank lines to separate functions and classes, and larger blocks of code inside functions.
• When possible, put comments on a line of their own.
• Use docstrings.
• Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) +
g(3, 4).
• Name your classes and functions consistently; the convention is to use UpperCamelCase for classes and
lowercase_with_underscores for functions and methods. Always use self as the name for the first
method argument (see A First Look at Classes for more on classes and methods).
• Don’t use fancy encodings if your code is meant to be used in international environments. Python’s default, UTF-8,
or even plain ASCII work best in any case.
• Likewise, don’t use non-ASCII characters in identifiers if there is only the slightest chance people speaking a
different language will read or maintain the code.
FIVE
DATA STRUCTURES
This chapter describes some things you’ve learned about already in more detail, and adds some new things as well.
The list data type has some more methods. Here are all of the methods of list objects:
list.append(x)
Add an item to the end of the list. Equivalent to a[len(a):] = [x].
list.extend(iterable)
Extend the list by appending all the items from the iterable. Equivalent to a[len(a):] = iterable.
list.insert(i, x)
Insert an item at a given position. The first argument is the index of the element before which to insert, so a.
insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).
list.remove(x)
Remove the first item from the list whose value is equal to x. It raises a ValueError if there is no such item.
list.pop([i ])
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and
returns the last item in the list. It raises an IndexError if the list is empty or the index is outside the list range.
list.clear()
Remove all items from the list. Equivalent to del a[:].
list.index(x[, start [, end ]])
Return zero-based index in the list of the first item whose value is equal to x. Raises a ValueError if there is
no such item.
The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a
particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence
rather than the start argument.
list.count(x)
Return the number of times x appears in the list.
list.sort(*, key=None, reverse=False)
Sort the items of the list in place (the arguments can be used for sort customization, see sorted() for their
explanation).
37
Python Tutorial, Release 3.12.2
list.reverse()
Reverse the elements of the list in place.
list.copy()
Return a shallow copy of the list. Equivalent to a[:].
An example that uses most of the list methods:
You might have noticed that methods like insert, remove or sort that only modify the list have no return value
printed – they return the default None.1 This is a design principle for all mutable data structures in Python.
Another thing you might notice is that not all data can be sorted or compared. For instance, [None, 'hello', 10]
doesn’t sort because integers can’t be compared to strings and None can’t be compared to other types. Also, there are
some types that don’t have a defined ordering relation. For example, 3+4j < 5+7j isn’t a valid comparison.
The list methods make it very easy to use a list as a stack, where the last element added is the first element retrieved
(“last-in, first-out”). To add an item to the top of the stack, use append(). To retrieve an item from the top of the
stack, use pop() without an explicit index. For example:
It is also possible to use a list as a queue, where the first element added is the first element retrieved (“first-in, first-out”);
however, lists are not efficient for this purpose. While appends and pops from the end of list are fast, doing inserts or pops
from the beginning of a list is slow (because all of the other elements have to be shifted by one).
To implement a queue, use collections.deque which was designed to have fast appends and pops from both ends.
For example:
List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element
is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of
those elements that satisfy a certain condition.
For example, assume we want to create a list of squares, like:
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Note that this creates (or overwrites) a variable named x that still exists after the loop completes. We can calculate the
list of squares without any side effects using:
or, equivalently:
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Note how the order of the for and if statements is the same in both these snippets.
If the expression is a tuple (e.g. the (x, y) in the previous example), it must be parenthesized.
The initial expression in a list comprehension can be any arbitrary expression, including another list comprehension.
Consider the following example of a 3x4 matrix implemented as a list of 3 lists of length 4:
>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
As we saw in the previous section, the inner list comprehension is evaluated in the context of the for that follows it, so
this example is equivalent to:
>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
In the real world, you should prefer built-in functions to complex flow statements. The zip() function would do a great
job for this use case:
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
See Unpacking Argument Lists for details on the asterisk in this line.
There is a way to remove an item from a list given its index instead of its value: the del statement. This differs from the
pop() method which returns a value. The del statement can also be used to remove slices from a list or clear the entire
list (which we did earlier by assignment of an empty list to the slice). For example:
>>> del a
Referencing the name a hereafter is an error (at least until another value is assigned to it). We’ll find other uses for del
later.
We saw that lists and strings have many common properties, such as indexing and slicing operations. They are two
examples of sequence data types (see typesseq). Since Python is an evolving language, other sequence data types may be
added. There is also another standard sequence data type: the tuple.
A tuple consists of a number of values separated by commas, for instance:
As you see, on output tuples are always enclosed in parentheses, so that nested tuples are interpreted correctly; they may
be input with or without surrounding parentheses, although often parentheses are necessary anyway (if the tuple is part
of a larger expression). It is not possible to assign to the individual items of a tuple, however it is possible to create tuples
which contain mutable objects, such as lists.
Though tuples may seem similar to lists, they are often used in different situations and for different purposes. Tuples
are immutable, and usually contain a heterogeneous sequence of elements that are accessed via unpacking (see later in
this section) or indexing (or even by attribute in the case of namedtuples). Lists are mutable, and their elements are
usually homogeneous and are accessed by iterating over the list.
A special problem is the construction of tuples containing 0 or 1 items: the syntax has some extra quirks to accommodate
these. Empty tuples are constructed by an empty pair of parentheses; a tuple with one item is constructed by following a
value with a comma (it is not sufficient to enclose a single value in parentheses). Ugly, but effective. For example:
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
The statement t = 12345, 54321, 'hello!' is an example of tuple packing: the values 12345, 54321 and
'hello!' are packed together in a tuple. The reverse operation is also possible:
>>> x, y, z = t
This is called, appropriately enough, sequence unpacking and works for any sequence on the right-hand side. Sequence
unpacking requires that there are as many variables on the left side of the equals sign as there are elements in the sequence.
Note that multiple assignment is really just a combination of tuple packing and sequence unpacking.
5.4 Sets
Python also includes a data type for sets. A set is an unordered collection with no duplicate elements. Basic uses in-
clude membership testing and eliminating duplicate entries. Set objects also support mathematical operations like union,
intersection, difference, and symmetric difference.
Curly braces or the set() function can be used to create sets. Note: to create an empty set you have to use set(), not
{}; the latter creates an empty dictionary, a data structure that we discuss in the next section.
Here is a brief demonstration:
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # fast membership testing
True
>>> 'crabgrass' in basket
False
5.4. Sets 43
Python Tutorial, Release 3.12.2
5.5 Dictionaries
Another useful data type built into Python is the dictionary (see typesmapping). Dictionaries are sometimes found in
other languages as “associative memories” or “associative arrays”. Unlike sequences, which are indexed by a range of
numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys.
Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either
directly or indirectly, it cannot be used as a key. You can’t use lists as keys, since lists can be modified in place using
index assignments, slice assignments, or methods like append() and extend().
It is best to think of a dictionary as a set of key: value pairs, with the requirement that the keys are unique (within one
dictionary). A pair of braces creates an empty dictionary: {}. Placing a comma-separated list of key:value pairs within
the braces adds initial key:value pairs to the dictionary; this is also the way dictionaries are written on output.
The main operations on a dictionary are storing a value with some key and extracting the value given the key. It is also
possible to delete a key:value pair with del. If you store using a key that is already in use, the old value associated with
that key is forgotten. It is an error to extract a value using a non-existent key.
Performing list(d) on a dictionary returns a list of all the keys used in the dictionary, in insertion order (if you want
it sorted, just use sorted(d) instead). To check whether a single key is in the dictionary, use the in keyword.
Here is a small example using a dictionary:
The dict() constructor builds dictionaries directly from sequences of key-value pairs: