Mathematisches Programmieren (AQA) – WS 2022/23 PDF
Document Details
Uploaded by MiraculousRaleigh8529
Universität Wien
2022
null
Oliver Hahn
Tags
Related
- Introduction to Object-Oriented Programming (OOP) PDF
- Programming in Python for Business Analytics Lecture Notes PDF
- Starting Out with Python - Classes and Object-Oriented Programming PDF
- Network Programming Control Flow Functions OOP in Python PDF
- Digital Skills & Python Programming - Chapter 7 PDF
- A Practical Introduction to Python Programming PDF
Summary
This document is a lecture from a course titled "Mathematisches Programmieren." It covers the topic of object-oriented programming (OOP) in Python using examples and explanations. The course is being taught during the winter semester of 2022/2023 at the University of Vienna.
Full Transcript
Objektorientiertes Programmieren Mathematisches Programmieren (250014 VU) Univ.-Prof. Dr. Oliver Hahn (Universität Wien) WS 2022/23 Mathematisches Programmieren (Hahn)...
Objektorientiertes Programmieren Mathematisches Programmieren (250014 VU) Univ.-Prof. Dr. Oliver Hahn (Universität Wien) WS 2022/23 Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 1 / 30 Prozedurales Programmieren Im POP(Procedure-Oriented-Programming)-Paradigma ist das Programm in Funktionen unterteilt, Daten sind v.a. global. Global Data Function 1 Local Data Function 2 Local Data … Function 3 Local Data Funktionen können sich dabei auch untereinander aufrufen. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 2 / 30 Prozedurales Programmieren in Python Beispiel: def func1( x ): return x*x * q # Multiplikation mit globaler Variable def func2( y ): ret = y+y # lokale Variable return ret if __name__ == "__main__": q = 5.0 a = 2.0 b = func1( a ) c = func2( b ) print(c) print( func2( func1( a ) ) ) Die Zeile if __name__... wird für jupyter notebooks nicht benötigt. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 3 / 30 Objektorientiertes Programmieren Im OOP(Object-Oriented-Programming)-Paradigma ist das Programm in Objekte unterteilt, die Daten bündeln, und Operationen nach außen anbieten. Objekte können dabei ’Daten’ von anderen Objekten sein. Object 1 Local Data Member Functions Object 3 Object 2 Local Data Local Data Member Functions Member Functions Datenlokalität: In OOP sollte es (fast) keine globalen Daten mehr geben. Datenzentralität: In OOP steht die Strukturierung der Daten und mögliche Operationen auf diesen Strukturen im Mittelpunkt. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 4 / 30 Objektorientiertes Programmieren Im OOP(Object-Oriented-Programming)-Paradigma ist das Programm in Objekte unterteilt, die Daten bündeln, und Operationen nach außen anbieten. Objekte können dabei ’Daten’ von anderen Objekten sein. Bremse aktuelle_Bremskraft anziehen(), lösen() Fahrrad Schaltung Schaltung, Bremse eingelegter_Gang aufsteigen(), bremsen() hochschalten(), runterschalten() Datenlokalität: In OOP sollte es (fast) keine globalen Daten mehr geben. Datenzentralität: In OOP steht die Strukturierung der Daten und mögliche Operationen auf diesen Strukturen im Mittelpunkt. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 4 / 30 Objektorientiertes Programmieren in Python Beispiel: Implementierung einer Klasse (incl. Docstring Dokumentation) class Additionsmaschine: """Eine Additionsmaschine""" def __init__( self, Anfangswert ): """Konstruktor der Additionsmaschine Args: Anfangswert (float): Startwert der Summe """ self.wert = Anfangswert def addiere( self, y ): """Addiert einen Wert zum internen Zustand Args: y (float): Wert der addiert wird """ self.wert += y def zeige_an( self ): """Gibt den internen Zustand aus""" print( f’Summe ist {self.wert}’) Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 5 / 30 Objektorientiertes Programmieren in Python Beispiel: Benutzung einer Klasse – es können einfach mehrere (unabhängige) Objekte erzeugt werden – ‘Instanzierung’ In : M1 = Additionsmaschine(1.0) In : M2 = Additionsmaschine(0.0) In : M1.addiere(2.0) In : M2.addiere(4.0) In : M1.addiere(3.0) In : M1.zeige_an() Summe ist 6.0 In : M2.zeige_an() Summe ist 4.0 Alle Details zu Klassen finden sich in der Python3 Dokumentation https://docs.python.org/3/tutorial/classes.html Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 6 / 30 Private Variablen und Funktionen OOP erlaubt üblicherweise die Unterscheidung zwischen Memberfunktionen und Variablen, die 1 nach außen sichtbar sind – und die somit das ‘Interface’ definieren 2 nicht nach außen sichtbar/verwendbar sind – und nur intern in der Klasse verwendet werden dürfen Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 7 / 30 Private Variablen und Funktionen In Python wird dies durch vorgestellten doppelten Unterstrich erreicht: class MyClass: def __init__( self, value ): self.x = value # normale Membervariable self.__x = value # private Membervariable def __f1( self ): # private Funktion return self.x def f2( self ): # publike Funktion return self.__x * self.__f1() Wir erhalten: In : a = MyClass( 2.0 ) In : a.__f1() AttributeError: ’MyClass’ object has no attribute ’__f1’ In : a.f2() 4.0 In : a.__x AttributeError: ’MyClass’ object has no attribute ’__x’ Nur Memberfkt., wie f2() dürfen also auf self.__f1() und self.__x zugreifen. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 8 / 30 Unterschiede POP vs. OOP Prozedurale Programmierung Objektorientierte Programmierung Fokus auf Funktionen Fokus auf Objekte/Klassen, Operatoren Daten global oder lokal Daten im Objekt, evtl. privat top-down bottom-up – Operatorüberladung – Vererbung Ideal für kleinere Programme Gut für kleine und ideal f. große Progr. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 9 / 30 Überladung – Ausgabe / Stringrepräsentation A priori hat eine Klasse, z.B. class MyClass: def __init__( self, val ): self.x = val keine Ausgabefunktion. Deshalb ergibt In : x = MyClass( 2.0 ) In : print( x ) einfach nur den Typ und die Speicheradresse des Objekts (der Instanz). Python weiß also erstmal nicht, wie eine Klasse dargestellt werden kann. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 10 / 30 Überladung – Ausgabe / Stringrepräsentation Man kann (und sollte!) die Repräsentation einer Klasse als String(str) wie folgt hinzufügen: class MyClass: def __init__( self, val ): self.x = val def __repr__(self): return f’MyClass( {self.x} )’ Die Memberfunktion __repr__ wird immer dann aufgerufen, wenn Python das Objekt als String repräsentieren soll, z.B. bei print. Wir erhalten nun wie erwartet In : x = MyClass( 2.0 ) In : print( x ) MyClass(2.0) Good practice: __repr__ sollte idealerweise Pythoncode ausgeben, der erlaubt das Objekt zu rekonstruieren (z.B. den Konstruktoraufruf). Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 11 / 30 Überladung – Ausgabe / Stringrepräsentation Optional kann man noch eine zusätzliche Konversion in String hinzufügen class MyClass: def __init__( self, val ): self.x = val def __repr__( self ): return f’MyClass( {self.x} )’ def __str__(self): return f’Wert = {self.x}’ Damit bekommen wir nun In : x = MyClass( 2.0 ) In : x MyClass( 2.0 ) In : print(x) Wert = 2.0 d.h. __str__ wird nun für print verwendet, __repr__ für die Repräsentation in anderen Ausgaben. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 12 / 30 Operatoren-Überladung Operatoren sind nur für die Standarddatentypen definiert. Aber wir können diese auch für unsere eigenen Klassen definieren. Erst dadurch werden z.B. Ausdrücke der Form a = MyClass() b = MyClass() # arithmestische Ausdruecke c = a*b + b # logische Ausdruecke if a > b: print(’a ist groesser als b’) möglich. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 13 / 30 Überladung – Gleichheits-/Ordnungsrelationen A priori können Objekte nicht verglichen und somit z.B. nicht sortiert werden: In : x = MyClass(1.0); y = MyClass(2.0) In : x < y TypeError: ’ 1 HNum( 1.0, 1.0 ) /Users/ohahn/testing.ipynb Cell 35 in HNum.__init__(self, a, b) 2 def __init__( self, a, b ): ----> 3 if a==b or a==-b: raise ValueError(’a==+-b not allowed’) 4 self.a = a 5 self.b = b ValueError: a==+-b not allowed Der Stacktrace hilft uns bei der Fehlersuche. In vielen Fällen liegt der Fehler bei uns und es ist ok abzubrechen. Manchmal wollen wir aber nicht, dass das Programm abbricht, sondern eine Ausnahme mit Fehlerbehandlung hinzufügen. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 22 / 30 Exceptions – Abfangen und Fehlerbehandlung Wir können Fehler aber auch abfangen und selbst behandeln, z.B. try: # Block wird ausgefuehrt und bei Fehler abgebrochen x = HNum( 1.0, 1.0 ) except ValueError: # Code falls ValueError auftaucht: print(’Unerlaubter Wert, Ergebnis wird ersetzt durch HNum( 1.0, 0.0)’) y = HNum( 1.0, 0.0 ) except: # Code falls andere Fehler auftauchen: print(’Anderer Fehler ist passiert’) else: # Code falls kein Fehler passiert ist: y = x * x finally: # Code der am Ende ausgefuehrt wird, egal ob Fehler passiert sind z = y * y # hier koennen wir mit z weiterarbeiten, da es wohldefiniert ist Ausserdem ist es möglich eigene Fehlerklassen zu definieren. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 23 / 30 Beispiel: Polygonklasse mit Rotation Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 24 / 30 Überladung – Zugriffsoperatoren Nehmen wir an, wir wollen eine Klasse für Polygone erstellen. Die Vertices sollen als Liste von 2-Tupeln gespeichert werden class MyPolygon: def __init__( self, nvertices ): self.nvertices = nvertices self.vertices = [ (None, None) ] * nvertices def __len__( self ): return self.nvertices Damit wir auf den Vertex i als object[i] zugreifen können, müssen wir Zugriffsoperatoren wie folgt definieren: def __getitem__( self, key ): # fuer Lesezugriff wie object[key] return self.vertices[key] def __setitem__( self, key, value ): # fuer Schreibzugriff object[key]=value self.vertices[key] = value Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 25 / 30 Überladung – Zugriffsoperatoren Damit erreichen wir, dass sich unsere Klasse wie gewünscht verhält In : poly = MyPolygon(3) In : poly = (0.0,1.0) In : poly = (2.0,2.0) In : poly = (1.0,3.0) In : print(poly) (1.0,3.0) In : for v in poly: print(v) (0.0, 1.0) (2.0, 2.0) (1.0, 3.0) Alle Details dazu aus der Python3 Dokumentation findet man hier: https://docs.python.org/3/reference/datamodel.html Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 26 / 30 Beispiel: Polygonklasse mit Rotation Rotationsgruppe SO(2, R) Die ebenen Rotationen Rθ um den Ursprung mit Winkel θ bilden die kommutative Lie-Gruppe SO(2). Ein Vertex v = (x, y ) ∈ R2 transformiert sich wie folgt Rθ v = (x cos θ − y sin θ, x sin θ + y cos θ) Das neutrale Element ist I := R0 , denn Iv = v. Das inverse Element ist R−θ , denn Rθ R−θ = R−θ Rθ = I. Assoziativ Rα (Rβ Rγ ) = (Rα Rβ )Rγ , und kommutativ Rα Rβ = Rβ Rα. Wir fügen somit zu unserer Polygonklasse hinzu def rotate( self, theta ): ct = math.cos( theta ); st = math.sin( theta ) # Kuerzel newvertices = [] # leere Liste f. neue Vertices for v in self.vertices: # Schleife ueber alle Vertices newvertices.append( (v*ct-v*st, v*st+v*ct) ) self.vertices = newvertices # ersetze alte mit neuen Vertices Wir brauchen natürlich noch ein ‘import math’ für die math. Funktionen. Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 27 / 30 Vererbung Wie können wir unsere Polygonklasse spezialisieren? Z.B. für Dreiecke und für regelmässige Fünfecke? Wir wollen dabei Funktionen/Operatoren, die für alle Polygone gelten weiterverwenden und nicht neu schreiben müssen. Lösung: Vererbung class MyTriangle(MyPolygon): def __init__( self ): MyPolygon.__init__( self, 3 ) # oder: super().__init__( 3 ) Erzeugt eine von MyPolygon abgeleitete Klasse und ruft den Konstruktor von MyPolygon explizit mit nvertices=3 auf. Wir erhalten In : t = MyTriangle() In : print( isinstance(t, MyPolygon) ) True In : print( isinstance(t, MyTriangle) ) True In : print( t.nvertices ) 3 Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 28 / 30 Vererbung Wir können nun Memberfunktionen zu MyTriangle hinzufügen, die spezifisch nur für Dreiecke verfügbar sind, z.B. den Flächeninhalt (nicht eind. f. nicht-konvexe Polygone) class MyTriangle( MyPolygon ): def __init__( self ): super().__init__( 3 ) def area( self ): v = self.vertices # Kuerzel det = v*(v-v) \ # Determinantenformel + v*(v-v) \ + v*(v-v) return abs(det)/2 Damit In : t = MyTriangle() In : t = (1.0,0.0); t = (0.0,0.0); t = (0.0,1.0) In : print(t.area()) 0.5 In : t.rotate( math.pi ); print( t.area() ) 0.5 In : print(t.vertices) [(-1.0, 1.224646799147e-16), (-0.0, 0.0), (-1.224646799147e-16, -1.0)] Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 29 / 30 Beispiel: Regelmäßige Pentagone Als letztes Anwendungsbeispiel noch ein regelmäßiges Pentagon. Wir können es aus einem Startpunkt durch sequentielle Rotation um 2π/5 erzeugen. Dies implementieren wir wie folgt: class MyVertex( MyPolygon ): """ein Monogon (?) mit einem einzelnen Vertex""" def __init__( self, point ): super().__init__(1) self.vertices = point class MyPentagon( MyPolygon ): """Klasse fuer regelmaessige Fuenfecke""" def __init__( self, rootpoint ): super().__init__(5) v = MyVertex( rootpoint ) for i in range(5): # erzeuge neuen Punkt durch Rotation v.rotate( 2*math.pi/5 ) self.vertices[i] = v.vertices Natürlich kann beliebig weiter vererbt werden... z.B. class MyColouredPentagon( MyPentagon ):... Mathematisches Programmieren (Hahn) Objektorientiertes Programmieren WS 2022/23 30 / 30