Skip to content

Commit 5a2ccc4

Browse files
committed
some more text on loops
1 parent d8c9d9c commit 5a2ccc4

File tree

6 files changed

+107
-9
lines changed

6 files changed

+107
-9
lines changed

bibliography/bibliography.bib

+24-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ @string { a_bommarito_michael
4545
@string { a_bose_cherokee = "Cherokee Boose" }
4646
@string { a_bott_ed = "Ed Bott" }
4747
@string { a_bradbury_james = "James Bradbury" }
48+
@string { a_brandl_georg = "Georg Brandl" }
4849
@string { a_brash_ron = "Ron Brash" }
4950
@string { a_brett_matthew = "Matthew Brett" }
5051
@string { a_bright_jonathan = "Jonathan Bright" }
@@ -136,6 +137,7 @@ @string { a_kim_sujin
136137
@string { a_kim_youil = "Youil Kim" }
137138
@string { a_klopf_andreas = "Andreas K{\"o}pf" }
138139
@string { a_knuth_donald_ervin = "Donald Ervin Knuth" }
140+
@string { a_kohn_tobias = "Tobias Kohn" }
139141
@string { a_konovalov_alexander = "Alexander Konovalov" }
140142
@string { a_korth_henry_f = "Henry F.\ Korth" }
141143
@string { a_krueger_richard = "Richard Krueger" }
@@ -234,6 +236,7 @@ @string { a_sobolev_nikita
234236
@string { a_sottet_jean_sebastien = "Jean{-}S{\'e}bastien Sottet" }
235237
@string { a_stein_clifford = "Clifford Stein" }
236238
@string { a_steiner_benoit = "Benoit Steiner" }
239+
@string { a_storchaka_serhiy = "Serhiy Storchaka" }
237240
@string { a_straffin_jr_philip_d = "Philip D.\ {Straffin~Jr.}" }
238241
@string { a_sudarshan_s = "S.\ Sudarshan" }
239242
@string { a_sullival_michael_j = "Michael J.\ Sullivan" }
@@ -844,7 +847,7 @@ @book{CLRS2009ITA
844847
publisher = p_mit_press,
845848
address = pa_mit_press,
846849
date = {2009},
847-
isbn = {978-0-262-03384}
850+
isbn = {978-0-262-03384-8}
848851
}
849852

850853
@book{CN2020ULB,
@@ -1261,6 +1264,26 @@ @techreport{PEP498
12611264
urldate = {2024-07-25},
12621265
}
12631266

1267+
@techreport{PEP515,
1268+
author = a_brandl_georg # and # a_storchaka_serhiy,
1269+
title = {Underscores in Numeric Literals},
1270+
xdata = {rep_pep},
1271+
number = {515},
1272+
date = {2016-02-10},
1273+
url = {https://peps.python.org/pep-0515},
1274+
urldate = {2024-09-23},
1275+
}
1276+
1277+
@techreport{PEP635,
1278+
author = a_kohn_tobias # and # a_van_rossum_guido,
1279+
title = {Structural Pattern Matching: Motivation and Rationale},
1280+
xdata = {rep_pep},
1281+
number = {635},
1282+
date = {2020-09-12/2021-02-08},
1283+
url = {https://peps.python.org/pep-0635},
1284+
urldate = {2024-09-23},
1285+
}
1286+
12641287
@inproceedings{PGMLBCKLGADKYDRTCSFBC2019PAISHPDLL,
12651288
author = a_paszke_adam # and # a_gross_sam # and # a_massa_francisco # and # a_lerer_adam # and # a_bradbury_james # and # a_chanan_gregory # and # a_killeen_trevor # and # a_lin_zeming # and # a_gimelshein_natalia # and # a_antiga_luca # and # a_desmaison_alban # and # a_klopf_andreas # and # a_yang_edward_z # and # a_devito_zachary # and # a_raison_martin # and # a_tejani_alykhan # and # a_chilamkurthy_sasank # and # a_steiner_benoit # and # a_fang_lu # and # a_bai_junjie # and # a_chintala_soumith,
12661289
title = {\pytorch: An Imperative Style, High-Performance Deep Learning Library},

styles/colors.sty

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
%% Listings Colors
1717
%%
1818
\colorlet{listing-background}{black!5!white}%
19+
\colorlet{listing-spaces}{Gray!85!listing-background}%
1920
\colorlet{listing-rule}{black!20!white}%
2021
%
2122
\colorlet{listing-line-numbers}{white!70!black}%

styles/listing.sty

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ $\downarrow$~~\expandafter\bashil{python3 #3}~~$\downarrow$%
279279
\center%
280280
\minipage{\linewidth}%
281281
\let\@old@lst@visiblespace\lst@visiblespace%
282-
\def\lst@visiblespace{{\color{Gray}\@old@lst@visiblespace}}%
282+
\def\lst@visiblespace{{\color{listing-spaces}\@old@lst@visiblespace}}%
283283
\lstset{%
284284
style=python_style,%
285285
showspaces=#1%

text/main/basics/simpleDataTypesAndOperations/float/float.tex

+8-2
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,15 @@
252252
When we write \pythonil{0.001} or \pythonil{0.0001} in a \python\ console, the output is still this same number.
253253
However, \pythonil{0.00009} is presented as \pythonil{9e-05}, which stands for~$9*10^{-5}$.%
254254
%
255-
\begin{sloppypar}%
256-
Did you know that you are allowed to insert underscores (\pythonil{_}\pythonIdx{\_}) anywhere in a number as a visual aid?
255+
Did you know that you are allowed to insert underscores (\pythonil{_}\pythonIdx{\_}) anywhere in a number (\pythonilIdx{int} or \pythonilIdx{float})as a visual aid~\cite{PEP515}?
257256
If not, you know now.
257+
%
258+
\bestPractice{underscoresInNumbers}{%
259+
If you need to specify large integers or floats, using underscores~(\pythonil{_}\pythonIdx{\_}) to separate groups of digits can be very helpful~\cite{PEP515}. %
260+
For example, \pythonil{37_859_378} is much easier to read than~\pythonil{37859378}.%
261+
}
262+
%
263+
\begin{sloppypar}%
258264
We can write $10^{15}$ as \pythonilIdx{float} by typing \pythonil{1_000_000_000_000_000.0}.
259265
This equals the much less readable \pythonil{1000000000000000.0}.
260266
We can do the same for $9*10^{15}$ by writing \pythonil{9_000_000_000_000_000.0} and get \pythonil{9000000000000000.0}.

text/main/basics/variables/assignment/assignment.tex

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@
159159
\endhsection%
160160
%
161161
\hsection{LIU Hui's Method and the Approximation of~$\pi$}%
162+
\label{sec:approximatePiLiuHui}%
162163
%
163164
\begin{figure}%
164165
\centering%

text/main/controlFlow/loops/loops.tex

+72-5
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,12 @@
2828
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{04_loops}{for_loop_pi_liu_hui.py}{--args format}{loops:for_loop_pi_liu_hui}{%
2929
A variant of \cref{lst:variables:pi_liu_hui} which uses a \pythonilIdx{for} loop instead of five copies of the same instructions.}%
3030
%
31-
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{04_loops}{for_loop_continue_break.py}{--args format}{loops:for_loop_continue_break}{%
32-
An example for the \pythonilIdx{continue} and \pythonilIdx{break} statements in a \pythonilIdx{for} loop.}%
33-
%
3431
The keyword~\pythonilIdx{for} is followed by a loop variable.
3532
Then comes the keyword~\pythonilIdx{in}, the \pythonil{sequence} we want to iterate over, and finally a colon~(\pythonilIdx{:}).
3633
This variable will iteratively take on the values in the \pythonil{sequence}.
3734
The loop body statements in the following, indented block are executed for each of these values.
38-
After the loop, we leave a blank line followed by the code that will be executed after the loop completes.
35+
Each time the body of the loop is executed is called an~\emph{iteration}\pythonIdx{iteration} of the loop.
36+
After the loop, we leave one blank line followed by the code that will be executed after the loop completes.
3937

4038
In its most simple form, the \pythonilIdx{for} loop is applied to a \pythonilIdx{range} of integer numbers.
4139
Ranges are sequences which work basically like slices\pythonIdx{slice} (see \cref{sec:lists:basicFunctions,sec:strBasicOperations}).
@@ -49,7 +47,76 @@
4947

5048
In \cref{lst:loops:for_loop_range}, we loop over exactly these ranges.
5149
In this listing, we try to create a dictionary (see \cref{sec:dictionaries}) where some integer numbers are mapped to their squares.
52-
We use four \pythonilIdx{for} loops to fill this dictionary with data.%
50+
We use four \pythonilIdx{for}~loops to fill this dictionary with data.
51+
In each of these first four \pythonilIdx{for}~loops, we use \pythonil{i} as the loop variable.
52+
53+
When iterating over the \pythonil{range(5)} in the first loop, \pythonil{i} will hold the value \pythonil{0} in the first iteration (=~execution of the loop body).
54+
The loop body \pythonil{squares[i] = i * i} will thus effectively be \pythonil{squares[0] = 0} and thus store the value~\pythonil{0} under key~\pythonil{0} into the dictionary \pythonil{squares}.
55+
In the second iteration, \pythonil{i} will hold the value~\pythonil{1}.
56+
Then, the body \pythonil{squares[i] = i * i} will effectively be \pythonil{squares[1] = 1}.
57+
In the third iteration, \pythonil{i} will hold the value~\pythonil{2} and the body will perform \pythonil{squares[2] = 4}.
58+
Next, \pythonil{i = 3} and \pythonil{squares[3] = 9} will be executed and in the laste iteration of the first loop, we store \pythonil{squares[4] = 16}.
59+
60+
In the second loop, which uses \pythonil{range(6, 9)}, \pythonil{i} will take on the values \pythonil{6}, \pythonil{7}, and \pythonil{8}, one by one.
61+
The dictionary \pythonil{squares} will thus be extended with the values \pythonil{squares[6] = 36}, \pythonil{squares[7] = 49}, and \pythonil{squares[8] = 64}.
62+
In the third loop, iterating over \pythonil{range(20, 27, 2)}, the following updates will be performed one by one \pythonil{squares[20] = 400}, \pythonil{squares[22] = 484}, \pythonil{squares[24] = 576}, and \pythonil{squares[26] = 676}.
63+
In the fourth loop, \pythonil{i} takes on the values of the sequence \pythonil{range(40, 30, -3)}, which has the negative step length~\pythonil{-3}.
64+
\pythonil{i} therefore first becomes~\pythonil{40}, then \pythonil{37} in the second iteration, then \pythonil{34}, and, finally,~\pythonil{31}.
65+
We then print\pythonIdx{print} the dictionary and get the expected output in \cref{exec:loops:for_loop_range}.%
66+
%
67+
\bestPractice{underscore}{%
68+
If we do not care about the value of a variable (or parameter), we should name it~\pythonil{_}\pythonIdx{\_}~\cite{PEP635}. %
69+
This information is useful for other programmers as well as static code analysis tools.%
70+
}%
71+
%
72+
At the end of \cref{lst:loops:for_loop_range} we show this special case:
73+
We want to print\pythonIdx{print} \pythonil{"Hello World!"} three times.
74+
Instead of copying the line \pythonil{print("Hello World!")} three times, we put it in a loop.
75+
However, nowhere in the loop body we care about the value of the loop variable.
76+
We thus simply call it \pythonil{_}\pythonIdx{\_}.
77+
If we would not call it that, then another programmer seeing our code (or a static code analysis tool for that matter) could be confused as to why we do not use the loop variable.
78+
Always remember that \inQuotes{real} code could be much more complicated, and any semantic hint we can include to convey our intentions will be helpful.
79+
80+
With these new tools at hand, we can revisit our old program \cref{lst:variables:pi_liu_hui} to approximate~$\pi$ from back in \cref{sec:approximatePiLiuHui}
81+
In this program, we executed the same code five times.
82+
Instead of doing this, we can put this into a loop, which reduces the lines of code from over~25 to about~10 in \cref{lst:loops:for_loop_pi_liu_hui}.
83+
The outputs in \cref{exec:variables:pi_liu_hui,exec:loops:for_loop_pi_liu_hui} are exactly the same.%
84+
%
85+
\endhsection%
86+
%
87+
\hsection{The \texttt{continue} and \texttt{break} Statements}%
88+
%
89+
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{04_loops}{for_loop_continue_break.py}{--args format}{loops:for_loop_continue_break}{%
90+
An example for the \pythonilIdx{continue} and \pythonilIdx{break} statements in a \pythonilIdx{for} loop.}%
91+
%
92+
Loops often have complex bodies, maybe containing conditional statements or other loops.
93+
It is not an uncommon situation that, after performing some computations in the body of the loop, we already know that we can continue directly with the next iteration instead of executing the remainder of the loop body.
94+
Sometimes we also find that we can entirely stop with the loop and continue with whatever instructions come after it, even if we did not yet exhaust the sequence over which we are iterating.
95+
The former can be achieved using the \pythonilIdx{continue} and the latter with the \pythonilIdx{break} statement.
96+
97+
An example for both statements is given in \cref{lst:loops:for_loop_continue_break}.
98+
Here, we iterate the variable~\pythonil{i} over the 15~values from~\pythonil{0} to~\pythonil{14}.
99+
In the loop body, we first create a string~\pythonil{s} with the current value of~\pythonil{i} via the \pgls{fstring} \pythonil{f"i is now \{i\}."}
100+
The very last instruction of the loop body, \pythonil{print(s)}\pythonIdx{print}, prints this string.
101+
102+
While \pythonil{i} would go from~\pythonil{0} to~\pythonil{14}, we actually want to abort the loop as soon as \pythonil{i} becomes greater than~\pythonil{10}.
103+
Instead of modifying the \pythonilIdx{range} over which we loop (which would be reasonable), we here want to use the \pythonilIdx{break} statement.
104+
We therefore wrap it into the conditional \pythonil{if i > 10:}, meaning that it will only be executed if~\pythonil{i > 10}.
105+
As soon as \pythonilIdx{break} is reached, the loop will immediately be aborted.
106+
No further instruction in the loop body is executed and no further iteration is performed.
107+
Instead, the process will continue after the loop, with the line~\pythonil{print("All done.")}.
108+
109+
If \pythonil{i > 10} did not hold, the rest of the loop body is executed.
110+
For the case that $\pythonil{i}\in\intRange{5}{8}$, we now want to directly jump to the next loop iteration by invoking the \pythonilIdx{continue}~statement.
111+
This means that if \pythonil{i == 5}, the \pythonilIdx{continue}~statement lets the control directly return to the head of the loop, which will set~\pythonil{i = 6}.
112+
This will happen until~\pythonil{i == 9}.
113+
The condition \pythonil{5 <= i <= 8} is \emph{not} met for all $\pythonil{i}\in\intRange{0}{4}\cup\intRange{9}{15}$.
114+
The next line, namely the \pythonil{print(s)}\pythonIdx{print}, can only be reached in these cases.
115+
Of course, we already know that we will never even reach this code as soon as \pythonil{i == 11}.
116+
117+
As a result the program will print the string~\pythonil{s} only for~$\pythonil{i}\in\intRange{0}{4}\cup\{9, 10\}$ before finally outputting~\textil{All done.}.
118+
This can be observed in the program output collected in \cref{exec:loops:for_loop_continue_break}.
119+
With \pythonilIdx{break} and \pythonilIdx{continue}, we now have two tools that can help us to either abort any loop prematurely or to abort the current iteration of the loop prematurely (and continue with the next one, if any), respectively.%
53120
%
54121
\endhsection%
55122
%

0 commit comments

Comments
 (0)