Skip to content

Commit 5879865

Browse files
committed
syntax examples now also in code repository
1 parent 6367aed commit 5879865

File tree

7 files changed

+24
-222
lines changed

7 files changed

+24
-222
lines changed

text/main/classes/basics/basics.tex

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,7 @@
4848
In this chapter, we discuss \pythoniles{class} in \python.
4949
Syntactly, \pythoniles{classes} follow the general blueprint below:%
5050
%
51-
\begin{pythonSyntax}
52-
class MyClass: # or `class MyClass(MyBaseClass)`
53-
"""Docstring of the class."""
54-
55-
def __init__(self) -> None:
56-
"""Docstring of the initializer __init__."""
57-
# initialize all attributes
58-
#: Meaning of attribute 1
59-
self.attribute_1: type hint = initial value
60-
# ...
61-
62-
def my_method(self, param1, param2) -> result:
63-
"""Docstring of my_method."""
64-
# compute something using the attributes
65-
\end{pythonSyntax}
51+
\pythonSyntax{syntax/class_init_method.py}%
6652
%
6753
\bestPractice{className}{\sloppy%
6854
Class names should follow the CapWords convention (often also called camel case), i.e., look like \pythonil{MyClass} or \pythonil{UniversityDepartment} (not \pythonil{my_class} or \pythonil{university_department})~\cite{PEP8}.}%

text/main/controlFlow/conditionals/conditionals.tex

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,7 @@
1010
The condition is provided as the kind of Boolean expressions that we already discussed back in \cref{sec:bool}.
1111
The syntax for this in \python\ is very simple:%
1212
%
13-
\begin{pythonSyntax}
14-
if booleanExpression:
15-
conditional statement 1
16-
conditional statement 2
17-
# ...
18-
19-
normal statement 1
20-
normal statement 2
21-
# ...
22-
\end{pythonSyntax}
13+
\pythonSyntax{syntax/if.py}%
2314
%
2415
\FloatBarrier%
2516
%
@@ -82,20 +73,7 @@
8273
This seems to be quite verbose and verbosity leads to confusion.
8374
So we are offered a better alternative: the \pythonil{if ... else}\pythonIdx{if{\idxdots}else} statement, which looks like this:%
8475
%
85-
\begin{pythonSyntax}
86-
if booleanExpression:
87-
conditional statement 1
88-
conditional statement 2
89-
# ...
90-
else:
91-
alternative statement 1
92-
alternative statement 2
93-
# ...
94-
95-
normal statement 1
96-
normal statement 2
97-
# ...
98-
\end{pythonSyntax}
76+
\pythonSyntax{syntax/if_else.py}%
9977
%
10078
The statement begins like a normal \pythonilIdx{if}~statement:
10179
\pythonil{if}, followed by a Boolean expression, followed by a colon~(\pythonilIdx{:}) marks the condition.
@@ -157,24 +135,7 @@
157135
Therefore, the \pythonilIdx{elif} statement has been developed, which can replace an \pythonil{else} containing just another \pythonil{if}.
158136
The syntax of a combined \pythonil{if ... elif} looks like this:%
159137
%
160-
\begin{pythonSyntax}
161-
if booleanExpression 1:
162-
conditional 1 statement 1
163-
conditional 1 statement 2
164-
# ...
165-
elif booleanExpression 2: # such block can be placed arbitrarily often
166-
conditional 2 statement 1
167-
conditional 2 statement 2
168-
# ...
169-
else: # this, too, is optional
170-
alternative statement 1
171-
alternative statement 2
172-
# ...
173-
174-
normal statement 1
175-
normal statement 2
176-
# ...
177-
\end{pythonSyntax}
138+
\pythonSyntax{syntax/if_elif_else.py}%
178139
%
179140
Notice that we can use arbitrarily many \pythonils{elif}\pythonIdx{elif} and, optionally, one~\pythonilIdx{else}.
180141
Only if the condition of the \pythonilIdx{if} evaluates to~\pythonilIdx{False}, the condition of the first~\pythonilIdx{elif} is checked.
@@ -254,11 +215,7 @@
254215
\python\ offers us a more compact syntax for this, and \ruff\ can again give us some idea about that in \cref{exec:conditionals:if_else_could_be_inline:ruff}:
255216
The inline \pythonil{if...then...else} statement, which has the following syntax:%
256217
%
257-
\begin{pythonSyntax}[false]
258-
variable = valueA if conditionForUsingValueA else valueB
259-
260-
variable = valueA if conditionForUsingValueA else (valueB if conditionForUsingValueB else valueC)
261-
\end{pythonSyntax}
218+
\pythonSyntax{syntax/if_else_inline.py}%
262219
%
263220
In the first variant, the value \pythonil{valueA} will be assigned to \pythonil{variable} if \pythonil{conditionForUsingValueA} evaluates to \pythonil{True}.
264221
Otherwise, \pythonil{valueB} is assigned.

text/main/controlFlow/exceptions/exceptions.tex

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -235,18 +235,7 @@
235235
Of course, multiple different types of \pythonilsIdx{Exception} may be raised, so we can have multiple \pythonilIdx{except} blocks.
236236
This looks like this:%
237237
%
238-
\begin{pythonSyntax}
239-
try: # Begin the try-except block.
240-
# Code that may raise an exception or that
241-
# calls a function that may rise one.
242-
except ExceptionType1 as ex1: # One exception type that can be caught.
243-
# Code the handles exceptions of type ExceptionType1.
244-
except ExceptionType2 as ex2: # Another exception type (optional).
245-
# Code the handles exceptions of type ExceptionType2 that are not
246-
# instances of ExceptionType1.
247-
248-
next statement # Executed only if there are no uncaught Exceptions.
249-
\end{pythonSyntax}
238+
\pythonSyntax{syntax/try_except.py}%
250239
\FloatBarrier%
251240
%
252241
\gitLoadAndExecPython{exceptions:try_except_str_index}{}{exceptions}{try_except_str_index.py}{}%
@@ -378,18 +367,7 @@
378367
One possible solution in such a situation is the \pythonilIdx{try}-\pythonilIdx{except}-\pythonilIdx{else} block.
379368
The difference to the \pythonilIdx{try}-\pythonilIdx{except} block is only that an \pythonilIdx{else} block follows, which is executed if and only if no exception occurred.%
380369
%
381-
\begin{pythonSyntax}
382-
try: # Begin the try-except block.
383-
# Code that may raise an exception or that
384-
# calls a function that may rise one.
385-
except ExceptionType1 as ex1: # One exception type that can be caught.
386-
# Code the handles exceptions of type ExceptionType1.
387-
# ... maybe more `except` blocks
388-
else:
389-
# Code executed if and only if no Exception occurred.
390-
391-
next statement # Executed only if there are no uncaught Exceptions.
392-
\end{pythonSyntax}
370+
\pythonSyntax{syntax/try_except_else.py}%
393371
%
394372
\gitLoadAndExecPython{exceptions:try_except_else}{}{exceptions}{try_except_else.py}{}%
395373
\listingPythonAndOutput{exceptions:try_except_else}{%
@@ -433,20 +411,7 @@
433411
Basically, we can add a \pythonilIdx{finally} block that contains the code that should always be executed.
434412
While we definitely need a \pythonilIdx{try} block that contains that code that may cause an error, we can optionally add \pythonilIdx{except} blocks to handle certain \pythonilsIdx{Exception} and an \pythonilIdx{else} block to be executed if no error occurs.%
435413
%
436-
\begin{pythonSyntax}
437-
try: # Begin the try-except block.
438-
# Code that may raise an exception or that
439-
# calls a function that may rise one.
440-
except ExceptionType1 as ex1: # The **optional** except blocks.
441-
# Code the handles exceptions of type ExceptionType1.
442-
# ... maybe more `except` blocks
443-
else: # The **optional** else block.
444-
# Code executed if and only if no Exception occurred.
445-
finally: # The **optional** finally block.
446-
# Code will always be executed, even if exceptions are uncaught.
447-
448-
next statement # Executed only if there are no uncaught Exceptions.
449-
\end{pythonSyntax}
414+
\pythonSyntax{syntax/try_except_else_finally.py}%
450415
%
451416
\gitLoadAndExecPythonAndErrors{exceptions:try_except_else_finally}{}{exceptions}{try_except_else_finally.py}{}%
452417
\listingPythonAndError{exceptions:try_except_else_finally}{%
@@ -599,15 +564,7 @@
599564
%
600565
The \pythonilIdx{with} statement has the following syntax, where the \pythonil{expression} is supposed to return a context manager~\cite{PSF:P3D:TPLR:WSCM,PSF:P3D:TPSL:CUFWSC,PSF:P3D:TPLR:TWS,PEP343}.%
601566
%
602-
\begin{pythonSyntax}
603-
with expression as variable:
604-
# block of code that works with variable
605-
606-
# or
607-
608-
with expression:
609-
# block of code
610-
\end{pythonSyntax}
567+
\pythonSyntax{syntax/with.py}%
611568
%
612569
Right now, we are still lacking some background knowledge needed to discuss what a context manager exactly is or how it works.
613570
We will therefore do this later in \cref{sec:dunder:contextManager}.

text/main/controlFlow/functions/functions.tex

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,7 @@
1010
\pythonIdx{def}\pythonIdx{function!def}%
1111
The syntax for defining our own functions in \python\ is as follows:%
1212
%
13-
\begin{pythonSyntax}
14-
def my_function(param_1: type, param_2: type, ...) -> result_type:
15-
"""
16-
Short sentence describing the function.
17-
18-
The title of the so-called docstring is a short sentence stating
19-
what the function does. It can be followed by several paragraphs of
20-
text describing it in more detail. Then follows the list of
21-
parameters, return values, and raised exceptions (if any).
22-
23-
:param param_1: the description of the first parameter (if any)
24-
:param param_2: the description of the second parameter (if any)
25-
:returns: the description of the return value (unless `-> None`).
26-
"""
27-
body of function 1
28-
body of function 2
29-
return result # if result_type is not None we return something
30-
31-
32-
normal statement 1
33-
normal statement 2
34-
my_function(argument_1, argument_2) # we can call the function like this
35-
\end{pythonSyntax}
13+
\pythonSyntax{syntax/function.py}%
3614
%
3715
\pythonIdx{function!def}A function in \python\ is created by using the \pythonilIdx{def}\pythonIdx{function!def} keyword, followed by the name of the function.%
3816
%
@@ -354,9 +332,7 @@
354332

355333
Tests are often defined in the form of several assertions assertions:\pythonIdx{assert}%
356334
%
357-
\begin{pythonSyntax}
358-
assert booleanExpr # raises AssertionError if not booleanExpr
359-
\end{pythonSyntax}
335+
\pythonSyntax{syntax/assert.py}%
360336
%
361337
An assertion is defined by the keyword \pythonilIdx{assert} followed by an arbitrary Boolean expression.
362338
If the Boolean expression evaluates to \pythonil{True}, then nothing happens.
@@ -711,9 +687,7 @@
711687
\pythonilIdx{Callable} is the \pgls{typeHint} for anything that can be called, i.e., functions~\cite{PSF:P3D:TPSL:ACO}.
712688
Like the \pgls{typeHint} for lists and tuples, it can be parameterized following the scheme~\cite{PEP612}:%
713689
%
714-
\begin{pythonSyntax}
715-
Callable[[parameterType1, parameterType2, ...], resultType]
716-
\end{pythonSyntax}
690+
\pythonSyntax{syntax/callable.py}%
717691
%
718692
In other words, inside the \pythonil{Callable[...]}, we first provide the list of parameter types, then a comma~\pythonil{,} followed by the return type.
719693
\pythonil{f: Callable[[float], float | int]} thus states that our function expects, as first parameter, \emph{another function}~\pythonil{f}.
@@ -735,35 +709,21 @@
735709
For this purpose, we need to pass the function~$f(x)=1$ as the~\pythonil{f} parameter of~\pythonil{integrate}.
736710
We could do this by writing:%
737711
%
738-
\begin{pythonSyntax}
739-
def const_1(x: float) -> float:
740-
return 1.0
741-
\end{pythonSyntax}
742-
%
743-
or%
744-
%
745-
\begin{pythonSyntax}
746-
def const_1(_: float) -> float:
747-
return 1.0
748-
\end{pythonSyntax}
712+
\pythonSyntax{syntax/const_unary_function.py}%
749713
%
750714
where the \pythonil{_}\pythonIdx{\_} indicates that we are actually going to ignore this parameter~(see~\cref{bp:underscore}).
751715
We could then invoke~\pythonil{integrate(const_1)}.
752716

753717
However, there also is a more compact way to specify functions that we are only going to use once:
754718
The so-called \pythonilsIdx{lambda}~\cite{PSF:P3D:TPLR:L}, which have the structure%
755719
%
756-
\begin{pythonSyntax}
757-
lambda param1, param2, ...: return value
758-
\end{pythonSyntax}
720+
\pythonSyntax{syntax/lambda.py}%
759721
%
760722
Due to the \pythonilIdx{:} in the notation, we cannot annotate \pythonilsIdx{lambda} with \pglspl{typeHint}.
761723
As a \pythonil{lambda} expression is very small and only used once, this does not pose a serious problem.
762724
Either way, since we need one parameter for our 1-returning-function and since we do not care about the value of this parameter, we can simply write:%
763725
%
764-
\begin{pythonSyntax}
765-
integrate(lambda _: 1.0)
766-
\end{pythonSyntax}
726+
\pythonSyntax{syntax/lambda_as_arg.py}%
767727
%
768728
\pythonilsIdx{lambda} are functions that we only want use in a single place.
769729
This is clearly the case for a function that ignores its parameter and always returns~\pythonil{1.0}.

text/main/controlFlow/iteration/iteration.tex

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,7 @@
107107
If we want to create a list with the logarithms of first five natural numbers, writing \pythonil{[log(1), log(2), log(3), log(4), log(5)]}\pythonIdx{log} looks clunky as well.
108108
Luckily, \python\ offers the much more convenient syntax of list comprehension\pythonIdx{list!comprehension}\pythonIdx{comprehension!list}~\cite{PEP202}:%
109109
%
110-
\begin{pythonSyntax}
111-
# Create a list from the items in a sequence; the condition is optional
112-
[expression for item in sequence if condition]
113-
\end{pythonSyntax}
110+
\pythonSyntax{syntax/list_comprehension.py}%
114111
%
115112
\gitLoadAndExecPython{iteration:simple_list_comprehension}{}{iteration}{simple_list_comprehension.py}{}%
116113
\listingPythonAndOutput{iteration:simple_list_comprehension}{%
@@ -343,10 +340,7 @@
343340
Set comprehension works very much the same as list comprehension.
344341
The corresponding syntax is as follows:%
345342
%
346-
\begin{pythonSyntax}
347-
# Create a set from the items in a sequence; the condition is optional
348-
{expression for item in sequence if condition}
349-
\end{pythonSyntax}
343+
\pythonSyntax{syntax/set_comprehension.py}%
350344
%
351345
\gitLoadAndExecPython{iteration:simple_set_comprehension}{}{iteration}{simple_set_comprehension.py}{}%
352346
\listingPythonAndOutput{iteration:simple_set_comprehension}{%
@@ -399,10 +393,7 @@
399393
Both of them use curly braces, but in dictionary comprehension\pythonIdx{dict!comprehension}\pythonIdx{comprehension!dict}, keys and values are separated by~\pythonilIdx{:}, whereas in a set comprehension, only single values are given.
400394
Dictionary comprehension has the following syntax:%
401395
%
402-
\begin{pythonSyntax}
403-
# Create a dict from the items in a sequence; the condition is optional
404-
{expression1: expression2 for item in sequence if condition}
405-
\end{pythonSyntax}
396+
\pythonSyntax{syntax/dict_comprehension.py}%
406397
%
407398
\gitLoadAndExecPython{iteration:simple_dict_comprehension}{}{iteration}{simple_dict_comprehension.py}{}%
408399
\listingPythonAndOutput{iteration:simple_dict_comprehension}{%
@@ -472,14 +463,7 @@
472463
To allow us to create \inQuotes{lazy} sequences that return their elements as needed (instead of keeping them all in memory all the time), generator expressions exist~\cite{PEP289}.
473464
The syntax for generator expressions is basically the same as for list expressions, except that we use parenthesis instead of square brackets:%
474465
%
475-
\begin{pythonSyntax}
476-
# A generator with the items in a sequence; the condition is optional
477-
(expression for item in sequence if condition)
478-
479-
# If generator expressions are single function parameters, then the
480-
# parentheses are unnecessary.
481-
function(expression for item in sequence if condition)
482-
\end{pythonSyntax}
466+
\pythonSyntax{syntax/generator_comprehension.py}%
483467
%
484468
\gitLoadAndExecPython{iteration:generator_expressions_next_1}{}{iteration}{generator_expressions_next_1.py}{}%
485469
\listingPythonAndOutput{iteration:generator_expressions_next_1}{%

text/main/controlFlow/loops/loops.tex

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,7 @@
1010
\pythonIdx{loop!for}%
1111
The most basic such sequence in \python\ may be the \pythonilIdx{for}~loop, which has the following pattern:%
1212
%
13-
\begin{pythonSyntax}
14-
for loopVariable in sequence:
15-
loop body statement 1
16-
loop body statement 2
17-
# ...
18-
19-
normal statement 1
20-
normal statement 2
21-
# ...
22-
\end{pythonSyntax}
23-
%
13+
\pythonSyntax{syntax/for_loop.py}%
2414
%
2515
\gitLoadAndExecPython{loops:for_loop_range}{}{loops}{for_loop_range.py}{}%
2616
\listingPythonAndOutput{loops:for_loop_range}{%
@@ -392,16 +382,7 @@
392382
Of course, we could try to pick a very very huge number and then \pythonil{break} the loop when the guesses converg {\dots} but that is just ugly.
393383
The \pythonilIdx{while} comes to rescue:%
394384
%
395-
\begin{pythonSyntax}
396-
while booleanExpression:
397-
loop body statement 1
398-
loop body statement 2
399-
# ...
400-
401-
normal statement 1
402-
normal statement 2
403-
# ...
404-
\end{pythonSyntax}
385+
\pythonSyntax{syntax/while_loop.py}%
405386
\FloatBarrier%
406387
%
407388
\gitLoadAndExecPython{loops:while_loop_sqrt}{}{loops}{while_loop_sqrt.py}{}%
@@ -454,31 +435,8 @@
454435
This is totally fine, but \python\ offers us a much less verbose method:
455436
Using the \pythonilIdx{else} statement at the bottom of the loop, which works for both \pythonilIdx{for} and \pythonilIdx{while} loops:%
456437
%
457-
\begin{pythonSyntax}
458-
for loopVariable in sequence:
459-
loop body statement 1
460-
loop body statement 2
461-
# ...
462-
else:
463-
code executed if break not invoked 1
464-
# ...
465-
normal statement 1
466-
normal statement 2
467-
# ...
468-
\end{pythonSyntax}
469-
%
470-
\begin{pythonSyntax}
471-
while booleanExpression:
472-
loop body statement 1
473-
loop body statement 2
474-
# ...
475-
else:
476-
code executed if break not invoked 1
477-
# ...
478-
normal statement 1
479-
normal statement 2
480-
# ...
481-
\end{pythonSyntax}
438+
\pythonSyntax{syntax/for_loop_else.py}%
439+
\pythonSyntax{syntax/while_loop_else.py}%
482440
%
483441
\gitLoadAndExecPython{loops:while_loop_search}{}{loops}{while_loop_search.py}{}%
484442
\listingPythonAndOutput{loops:while_loop_search}{%

0 commit comments

Comments
 (0)