Skip to content

Commit 3a95a8d

Browse files
committed
🎨 Rearrange control flow section
* Update boolean operators * Rename if-elif-else * Update exceptions
1 parent 67a7a88 commit 3a95a8d

File tree

26 files changed

+301
-241
lines changed

26 files changed

+301
-241
lines changed

docs/appendix/checks.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,8 @@ Checks
467467
>>> print(personal_data[who])
468468
60
469469
470-
:doc:`/control-flows/loops`
471-
---------------------------
470+
:doc:`/control-flow/loops`
471+
--------------------------
472472

473473
* Removes all negative numbers from the list ``x = [ -2, -1, 0, 1, 2, 3]``.
474474

@@ -532,8 +532,8 @@ Checks
532532
>>> {x: x**3 for x in range(1, 5)}
533533
{1: 1, 2: 8, 3: 27, 4: 64}
534534
535-
:doc:`/control-flows/exceptions`
536-
--------------------------------
535+
:doc:`/control-flow/exceptions`
536+
-------------------------------
537537

538538
* Write code that receives two numbers and divides the first number by the
539539
second. Check if the :class:`python3:ZeroDivisionError` occurs when the second

docs/control-flow/boolean.rst

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Boolean values and expressions
2+
==============================
3+
4+
In Python, there are several ways to express Boolean values; the Boolean
5+
constant ``False``, ``0``, the Python type :doc:`../types/none` and empty
6+
values (for example the empty list ``[]`` or the empty string ``""``) are all
7+
considered ``False``. The Boolean constant ``True`` and everything else is
8+
considered ``True``.
9+
10+
``<``, ``<=``, ``==``, ``>``, ``>=``
11+
compares values:
12+
13+
.. code-block:: pycon
14+
15+
>>> x = 3
16+
>>> y = 3.0
17+
>>> z = [3, 4, 5]
18+
>>> x == y
19+
True
20+
21+
However, you should never compare calculated floating point numbers with
22+
each other:
23+
24+
.. code-block:: pycon
25+
26+
>>> u = 0.6 * 7
27+
>>> v = 0.7 * 6
28+
>>> u == v
29+
False
30+
>>> u
31+
4.2
32+
>>> v
33+
4.199999999999999
34+
35+
``is``, ``is not``, ``in``, ``not in``
36+
checks the identity:
37+
38+
.. code-block:: pycon
39+
40+
>>> x is y
41+
False
42+
>>> x is not y
43+
True
44+
>>> x in z
45+
True
46+
>>> id(x)
47+
4375911432
48+
>>> id(y)
49+
4367574480
50+
>>> id(z[0])
51+
4375911432
52+
53+
If ``x`` and ``z[0]`` have the same ID in memory, this means that we are
54+
referring to the same object in two places.
55+
56+
Most frequently, ``is`` and ``is not`` are used in conjunction with
57+
:doc:`../types/none`:
58+
59+
.. code-block:: pycon
60+
61+
>>> x is None
62+
False
63+
>>> x is not None
64+
True
65+
66+
The Python style guide in :pep:`8` says that you should use identity to
67+
compare with :doc:`../types/none`. So you should never use ``x == None``,
68+
but ``x is None`` instead.
69+
70+
``and``, ``not``, ``or``
71+
are logical operators that we can use to link the above checks:
72+
73+
.. code-block:: pycon
74+
75+
>>> x is y and x is z[0]
76+
False
77+
>>> x is y or x is z[0]
78+
True
79+
>>> x is y and not x is z[0]
80+
False
81+
>>> x is z[0] and not x is y
82+
True

docs/control-flow/conditional.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Conditional statements
2+
======================
3+
4+
The code block after the first true condition of an ``if`` or ``elif`` statement
5+
is executed. If none of the conditions are true, the code block after the
6+
``else`` is executed:
7+
8+
.. code-block:: pycon
9+
:linenos:
10+
11+
>>> x = 1
12+
>>> if x < 1:
13+
... x = 2
14+
... y = 3
15+
... elif x > 1:
16+
... x = 4
17+
... y = 5
18+
... else:
19+
... x = 6
20+
... y = 7
21+
...
22+
>>> x, y
23+
(6, 7)
24+
25+
Python uses indentations to delimit blocks. No explicit delimiters such as
26+
brackets or curly braces are required. Each block consists of one or more
27+
statements separated by line breaks. All these statements must be at the same
28+
indentation level.
29+
30+
Line 5
31+
The ``elif`` statement looks like the ``if`` statement and works in the same
32+
way, but with two important differences:
33+
34+
* ``elif`` is only allowed after an ``if`` statement or another ``elif``
35+
statement
36+
* you can use as many ``elif`` statements as you need
37+
38+
Line 8
39+
The optional ``else`` clause denotes a code block that is only executed if
40+
the other conditional blocks, ``if`` and ``elif``, are all false.
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ class EmptyFileError(Exception):
33

44

55
filenames = ["myFile1.py", "nonExistent.py", "emptyFile.py", "myFile2.py"]
6+
67
for file in filenames:
78
try:
89
f = open(file, "r")
910
line = f.readline()
1011
if line == "":
11-
f.close()
1212
raise EmptyFileError(f"{file} is empty")
13-
except IOError as error:
13+
except OSError as error:
1414
print(f"Cannot open file {file}: {error.strerror}")
1515
except EmptyFileError as error:
1616
print(error)
1717
else:
1818
print(f"{file}: {f.readline()}")
1919
finally:
2020
print("File", file, "processed")
21+
f.close()

docs/control-flow/exceptions.rst

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
Exceptions
2+
==========
3+
4+
This section deals with exceptions, which are language functions that
5+
specifically handle unusual circumstances during the execution of a programme.
6+
The most common exception is error handling, but they can also be used
7+
effectively for many other purposes. Python provides a comprehensive set of
8+
exceptions, and you can define new exceptions for your own purposes.
9+
10+
An exception is an object that is automatically created by Python functions with
11+
a :ref:`raise <python3:raise>` statement, for example with:
12+
13+
.. literalinclude:: exceptions.py
14+
:language: python
15+
:linenos:
16+
:lines: 11-12
17+
:lineno-start: 11
18+
19+
The :ref:`raise <python3:raise>` statement causes the Python programme to be
20+
executed in a different way than is usually intended: The current call chain is
21+
searched for a handler that can handle the generated exception. If such a
22+
handler is found, it is called and can access the exception object to obtain
23+
further information, as in our :class:`EmptyFileError` example:
24+
25+
.. literalinclude:: exceptions.py
26+
:language: python
27+
:linenos:
28+
:lines: 1-2
29+
30+
This defines your own exception type, which inherits from the ``Exception`` base
31+
type.
32+
33+
You can find an overview of the class hierarchy of built-in exceptions at
34+
`Exception hierarchy
35+
<https://docs.python.org/3/library/exceptions.html#exception-hierarchy>`_ in the
36+
Python documentation. Each exception type is a Python class that inherits from
37+
its parent exception type. For example, a ``ZeroDivisionError`` is also an
38+
``ArithmeticError``, an ``Exception`` and also a ``BaseException`` by
39+
inheritance. This hierarchy is intentional: most exceptions inherit from
40+
``Exception``, and it is strongly recommended that all user-defined exceptions
41+
also subclass ``Exception`` and not ``BaseException``:
42+
43+
It is possible to create different types of exceptions to reflect the actual
44+
cause of the reported error or exceptional circumstance.
45+
46+
.. literalinclude:: exceptions.py
47+
:language: python
48+
:linenos:
49+
:lines: 8-16
50+
:lineno-start: 8
51+
52+
If an ``OSError`` or an ``EmptyFileError`` occurs in the ``try`` block during
53+
the execution of :func:`open`, the corresponding ``except`` block is executed.
54+
55+
If no suitable exception handler is found, the programme terminates with an
56+
error message. We therefore add ``else`` and ``finally`` to our
57+
``try``-``except`` statements:
58+
59+
.. literalinclude:: exceptions.py
60+
:language: python
61+
:linenos:
62+
:lines: 17-21
63+
:lineno-start: 17
64+
65+
Now we can define a list of different file types so that our complete code looks
66+
like this:
67+
68+
.. literalinclude:: exceptions.py
69+
:language: python
70+
:linenos:
71+
:lines: 1-
72+
:lineno-start: 1
73+
74+
Line 7
75+
If an ``OSError`` or ``EmptyFileError`` occurs during the execution of the
76+
statements in the ``try`` block, the corresponding ``except`` block is
77+
executed.
78+
Line 9
79+
An ``OSError`` could be triggered here.
80+
Line 12
81+
Here you trigger the ``EmptyFileError``.
82+
Line 17
83+
The ``else`` clause is optional; it is executed if no exception occurs in
84+
the ``try`` block.
85+
Line 19
86+
The ``finally`` clause is also optional and is executed at the end of the
87+
block, regardless of whether an exception was triggered or not.
88+
89+
.. note::
90+
The way Python handles error situations in general differs from some other
91+
languages, such as Java. These languages check possible errors as far as
92+
possible before they occur, as handling exceptions after they occur is
93+
costly. This is sometimes referred to as the :abbr:`LBYL (Look before you
94+
leap)` approach.
95+
96+
Python, on the other hand, relies more on exceptions to handle errors after
97+
they occur. Although this reliance may seem risky, when exceptions are used
98+
correctly, the code is less cumbersome and easier to read, and errors are
99+
only handled when they occur. This Pythonic approach to error handling is
100+
often described as :abbr:`EAFP (easier to ask forgiveness than permission)`.
101+
102+
Checks
103+
------
104+
105+
* Write code that receives two numbers and divides the first number by the
106+
second. Check if the :class:`python3:ZeroDivisionError` occurs when the second
107+
number is ``0`` and catch it.
108+
109+
* If :class:`MyError` inherits from :class:`Exception`, what is the difference
110+
between ``except Exception as e`` and ``except MyError as e``?
111+
112+
* Write a simple program that receives a number and then uses the :func:`assert`
113+
statement to throw an :class:`exception <python3:Exception>` if the number is
114+
``0``.
115+
116+
* Writes a user-defined exception :class:`Outliers` that throws an exception if
117+
the variable ``x`` is greater or less than ``3``?
118+
119+
* Is the check whether an object is a list (:ref:`Check: list <check-list>`)
120+
programming in the style of :abbr:`LBYL (look before you leap)` or
121+
:abbr:`EAFP (easier to ask forgiveness than permission)`?

docs/control-flow/index.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Control flow
2+
============
3+
4+
Python has a whole range of structures for controlling code execution and
5+
programme flow, including common branches and loops:
6+
7+
:doc:`boolean`
8+
check values and identity and allow links between the two.
9+
:doc:`conditional`
10+
execute the code block after the first true condition of an ``if`` or
11+
``elif`` statement; if neither condition is true, the code block is executed
12+
after the ``else``.
13+
:doc:`loops`
14+
While ``while`` loops are executed as long as the condition is true, ``for``
15+
loops iterate over :doc:`../types/sequences-sets/lists`,
16+
:doc:`../types/sequences-sets/tuples` and
17+
:doc:`../types/sequences-sets/sets`.
18+
:doc:`exceptions`
19+
usually deal with errors that occur during the execution of programmes.
20+
:doc:`with`
21+
regulates access to files, the locking of threads and the suppression of
22+
:doc:`exceptions`, among other things.
23+
24+
.. toctree::
25+
:titlesonly:
26+
:hidden:
27+
28+
boolean
29+
conditional
30+
loops
31+
exceptions
32+
with
File renamed without changes.

0 commit comments

Comments
 (0)