Skip to content

Commit 42e64a4

Browse files
committed
first steps into class inheritance
1 parent c27be91 commit 42e64a4

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

text/main/classes/basics/basics.tex

+6-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,12 @@
374374
Our \pythonilIdx{KahanSum}, however, uses only three variables for the whole summation process.
375375
It does not dynamically allocate more memory.
376376
Also, the number of steps it performs are constant for each addition, whereas the algorithm by \citeauthor{S1997APFPAAFRGP} needs to do a number of steps that depends on the current length of its internal datastructure.
377-
Thus, \pythonil{KahanSum} is indeed a very nice compromise solution, which offers higher precision than normal summing but retains the same memory and time complexity.%
377+
Thus, \pythonil{KahanSum} is indeed a very nice compromise solution, which offers higher precision than normal summing but retains the same memory and time complexity.
378+
379+
Another advantage of our \pythonil{KahanSum} over the function \pythonilIdx{fsum} is that we can use it in a more versatile fashion.
380+
We do not need to have all values ready in an \pythonilIdx{Iterable}.
381+
If we had a generator of a sequence of values and wanted to compute the sum of the values themselves as well as the sum of their squares, we could simply use two instances \pythonil{KahanSum} while iterating over the sequence.
382+
With \pythonilIdx{fsum}, we would need to iterate over the sequence twice, which may not be practical if the sequence is generated from some outside source and was too long to just store it in memory.%
378383
%
379384
\FloatBarrier%
380385
\endhsection%

text/main/classes/inheritance/inheritance.tex

+54-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
A class for representing shapes in the two-dimensional Euclidean plane.}%
66
%
77
\gitPython{\programmingWithPythonCodeRepo}{08_classes/circle.py}{--args format}{classes:circle}{%
8-
A circle is a special shape, namely the set of all points whose distance from the center of the cirlce is exactly the radius.}%
8+
A circle is a special shape, namely the set of all points whose distance from the center of the circle is exactly the radius.}%
9+
%
10+
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{08_classes}{circle_user.py}{--args format}{classes:circle_user}{%
11+
An example of using our class \pythonil{Circle} from \cref{lst:classes:circle}.}%
912
%
1013
\gitPython{\programmingWithPythonCodeRepo}{08_classes/polygon.py}{--args format}{classes:polygon}{%
1114
Polygons are special shapes delimited by straight lines between corner points.}%
@@ -16,4 +19,54 @@
1619
\gitPython{\programmingWithPythonCodeRepo}{08_classes/triangle.py}{--args format}{classes:triangle}{%
1720
A triangle is a polygon spanned by three points in a plane.}%
1821
%
22+
We already learned that classes are a proper tool four grouping data and operations on the data together into one semantic unit.
23+
Classes also offer the concept of inheritance, which basically means \inQuotes{specialization}.
24+
Imagine that we would wanted to represent all geometrical shapes in a two-dimensional plance.
25+
Each shape has an associated area as well as a perimeter.
26+
We could create a class\pythonIdx{class} \pythonil{Shape} that provides two methods, \pythonil{area} and \pythonil{perimeter}, returning the area in in area units and the perimeter length in length units, respectively.
27+
28+
A circle is a special shape.
29+
It does have a center as well as a radius.
30+
Knowing these two attributes, we can compute the area and perimeter.
31+
If we wanted to express this in terms of classes, we could say that the class\pythonIdx{class} \pythonil{Circle} is a special subclass of class~\pythonil{Shape}.
32+
It would have two attributes, \pythonil{center} (which could be an instance of \pythonil{Point}) and \pythonil{radius}, which would be a \pythonil{float}.
33+
The methods \pythonil{area} and \pythonil{perimeter} could then be implemented appropriately and use these attributes.
34+
35+
This is already how inheritance works:
36+
If we want that a new class\pythonIdx{class}~\pythonil{Circle} inherits from a class\pythonIdx{class}~\pythonil{Shape}, all we have to do is to write \pythonil{class Circle(Shape):} instead of just \pythonil{class Circle:} when declaring the new circle class\pythonIdx{class}.
37+
Of course, we first need to create the class\pythonIdx{class}~\pythonil{Shape}.
38+
39+
We do this in \cref{lst:classes:shape}.
40+
In this listing, we define \pythonil{Shape} as a new class\pythonIdx{class}.
41+
We want that this class has two methods, \pythonil{area} and \pythonil{perimeter}.
42+
The class\pythonIdx{class}~\pythonil{Shape} is not intended for being instantiated.
43+
Instead, we just want it to be the base class\pythonIdx{class} for \inQuotes{special} shapes.
44+
It does not have any attribute.
45+
Of course, we cannot really compute the area or the perimeter of such an abstract object.
46+
So both methods raise\pythonIdx{raise} an \pythonilIdx{NotImplementedError}.
47+
If someone would like to actually instantiate \pythonil{Shape} by doing, say, \pythonil{s = Shape()} and then invoke \pythonil{s.perimeter()}, this would fail.
48+
49+
While \pythonil{Shape} itself is useless, it allows us to create different specialized subclasses that do implement \pythonil{area} and \pythonil{perimeter}.
50+
The user of these classes could then treat all of these different subclasses in the same way, because all of them support the interface defined by~\pythonil{Shape}.
51+
52+
In \cref{lst:classes:circle}, we define the class\pythonIdx{class}~\pythonil{Circle}.
53+
By writing \pythonil{class Circle(Shape)}\pythonIdx{class}, we declare it as a subclass\pythonIdx{class} of \pythonil{Shape}.
54+
Its constructor \pythonilIdx{\_\_init\_\_}, we supply two parameters, \pythonil{center}, which is an instance of our class \pythonil{Point} from \cref{lst:classes:point}, and \pythonil{radius}, which can either be an \pythonil{int} or a \pythonil{float}.
55+
The constructor first checks if \pythonil{radius} is a finite and positive number.
56+
Otherwise, it raises\pythonIdx{raise} a \pythonilIdx{ValueError}.
57+
The constructor of the class\pythonIdx{class}~\pythonil{Point} already ensures that both coordinates of \pythonil{point} will be finite.
58+
This ensures that we indeed create valid circles.
59+
We store \pythonil{center} and \pythonil{radius} in two attributes of the same names.
60+
We annotate them with the \pgls{typeHint} \pythonilIdx{Final}, which means that they should not be changed after the object is constructed.
61+
We can now implement the function \pythonil{area} to return~$\numberPi\pythonil{radius}^2$ and \pythonil{perimeter} to return~$2\numberPi\pythonil{radius}$.
62+
With this, the complete interface defined by the superclass\pythonIdx{class}~\pythonil{Shape} is now filled with meaning.
63+
64+
In \cref{lst:classes:circle_user}, we explore how this new class can be used.
65+
We create the new instance \pythonil{circ} of \pythonil{Circle} by providing the \pythonil{point=Point(2, 3)} and \pythonil{radius=4}.
66+
These parameters are indeed reflected by the corresponding attributes.
67+
We also confirm that \pythonil{isinstance(cir, Circle)}\pythonIdx{isinstance} is \pythonil{True}.
68+
It also holds that \pythonil{isinstance(cir, Shape)}\pythonIdx{isinstance}.
69+
Every instance of \pythonil{Circle} is also an instance of \pythonil{Shape}.
70+
Because \pythonil{Circle} is a special case of \pythonil{Shape}.
71+
%
1972
\endhsection%

text/main/controlFlow/exceptions/exceptions.tex

+1-1
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@
666666
.4 \pythonilIdx{TimeoutError}\DTcomment{an operation timed out}.
667667
.3 \pythonilIdx{ReferenceError}\DTcomment{a weakly-referenced object is accessed after being garbage collected}.
668668
.3 \pythonilIdx{RuntimeError}\DTcomment{an error that does not fall into the other categories}.
669-
.4 \pythonilIdx{NotImplementedError}\DTcomment{a method has not yet been implement, but will be later}.
669+
.4 \pythonilIdx{NotImplementedError}\DTcomment{a method is not yet implement, but will be later, see, e.g., \cref{sec:inheritance}}.
670670
.4 \pythonilIdx{PythonFinalizationError}\DTcomment{an operation is blocked during interpreter shutdown}.
671671
.4 \pythonilIdx{RecursionError}\DTcomment{the maximum recursion depth of functions is reached}.
672672
.3 \pythonilIdx{StopAsyncIteration}\DTcomment{signals the end of an asynchronous iteration; not an error}.

0 commit comments

Comments
 (0)