Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
talit:tutorial_oop3 [2026-04-09 06:47] hoftalit:tutorial_oop3 [2026-06-01 15:25] (aktuell) hof
Zeile 1: Zeile 1:
 # Objekt-orientierte Programmierung # Objekt-orientierte Programmierung
 +
 +<nodisp 2>
 +++++ Notizen für 2027|
 +  * Feedback sca / Beobachtung: es bleibt wenig OO hängen:
 +    * Instanz vs. Klasse
 +    * Methode?
 +    * Warum das ganze?
 +  * Abhilfe: weniger ist mehr
 +    * Nur zwei Klassen: `WordPair`, `VocabularyUnit`
 +    * Stats in WordPair integrieren
 +    * Kerninhalte: WordPair, Unit, Learning function (ohne OO), Serialisierung
 +    * LearningStrategy, StopCriterion als Additum für Highflyers behalten.
 +++++
 +</nodisp>
  
 Code mit vielen Eigenschaften kann schnell unübersichtlich werden - sogar selbst geschriebener Code altert schlecht und ist nach wenigen Wochen unlesbar. Was macht der folgende Code? Code mit vielen Eigenschaften kann schnell unübersichtlich werden - sogar selbst geschriebener Code altert schlecht und ist nach wenigen Wochen unlesbar. Was macht der folgende Code?
Zeile 99: Zeile 113:
 Objekte werden manchmal auch als _Instanzen_ (einer Klasse) bezeichnet; im obigen Code-Beispiel ist das in der Variable `tree` gespeicherte Objekt eine Instanz der Klasse `WordPair`. Objekte werden manchmal auch als _Instanzen_ (einer Klasse) bezeichnet; im obigen Code-Beispiel ist das in der Variable `tree` gespeicherte Objekt eine Instanz der Klasse `WordPair`.
 #### Coding Conventions #### Coding Conventions
-  * Klassennamen in `CamelCase` +  * Klassennamen in `CamelCase` ([[wp>Camel_Case]]) 
-  * Methoden und Attribute in `lower_case_with_underscores()`+  * Methoden und Attribute in `lower_case_with_underscores()` ([[wp>Snake_case]])
   * Dokumentation mit `"""doc strings"""`   * Dokumentation mit `"""doc strings"""`
     * Der doc-string für die ganze Klasse beschreibt deren Funktion. Typischerweise ist der erste Satz die Vervollständigung des Satzanfangs "Ein <classname> ist ...". Im obigen Beispiel "[A WordPair is] a word and its translation.".     * Der doc-string für die ganze Klasse beschreibt deren Funktion. Typischerweise ist der erste Satz die Vervollständigung des Satzanfangs "Ein <classname> ist ...". Im obigen Beispiel "[A WordPair is] a word and its translation.".
     * Der doc-string für Methoden beschreibt die Tätigkeit der Methode. Typischerweise beginnt der Satz mit einem Verb und ist die Vervollständigung des Satzanfangs "Die <functionname> Methode ...". Im obigen Beispiel "[The reversed method] returns a copy of the pair in the reverse direction."     * Der doc-string für Methoden beschreibt die Tätigkeit der Methode. Typischerweise beginnt der Satz mit einem Verb und ist die Vervollständigung des Satzanfangs "Die <functionname> Methode ...". Im obigen Beispiel "[The reversed method] returns a copy of the pair in the reverse direction."
- 
  
 ### Aufgabe A ### Aufgabe A
Zeile 115: Zeile 128:
 Wir möchten zusätzlich eine Klasse `VocabularyUnit` haben, die eine Liste von `WordPair`s speichert. Wie sieht die `__init__` Methode dieser Klasse aus? Wir möchten zusätzlich eine Klasse `VocabularyUnit` haben, die eine Liste von `WordPair`s speichert. Wie sieht die `__init__` Methode dieser Klasse aus?
  
-Als drittes benötigen wir eine Klasse `ConsoleLearner` mit einer Methode `learn(unit)`, die alle Wort-Paare abfragt.+Als drittes benötigen wir eine Klasse `ConsoleLearner` mit einer Methode `learn(unit)`, die alle Wort-Paare einer `VocabularyUnit` abfragt.
   * um das Terminal zu leeren kannst du `print("\033c", end="")` benützen   * um das Terminal zu leeren kannst du `print("\033c", end="")` benützen
   * um nur die aktuelle Zeile im Terminal zu löschen, verwendest du `print("\033[H\033[J", end="")`   * um nur die aktuelle Zeile im Terminal zu löschen, verwendest du `print("\033[H\033[J", end="")`
Zeile 121: Zeile 134:
  
 ## Objekte und Klassen in Python ## Objekte und Klassen in Python
-<html><script type="module" src="https://bottom.ch/editor/stable/bottom-editor.js"></script></html> 
  
 Jeder Wert in Python ist eigentlich ein Objekt. Zahlen sind Objekte der Klassen `int` oder `float`. Die Klasse eines Objekts kann mit der Funktion `type()` herausgefunden werden: Jeder Wert in Python ist eigentlich ein Objekt. Zahlen sind Objekte der Klassen `int` oder `float`. Die Klasse eines Objekts kann mit der Funktion `type()` herausgefunden werden:
  
-<html><bottom-editor>print(f'42 is of class {type(42)}')+<bottom-editor>print(f'42 is of class {type(42)}')
 print(f'3.14 is of class {type(3.14)}') print(f'3.14 is of class {type(3.14)}')
-print(f'"foobar" is of class {type("foobar")}')</bottom-editor></html>+print(f'"foobar" is of class {type("foobar")}')</bottom-editor>
  
 Sogar Funktionen sind Objekte: Sogar Funktionen sind Objekte:
  
-<html><bottom-editor>print(f'len() is of class {type(len)}')</bottom-editor></html>+<bottom-editor>print(f'len() is of class {type(len)}')</bottom-editor>
  
 ### Vererbung ### Vererbung
Zeile 139: Zeile 151:
 Wir können die Vererbung explizit angeben: Wir können die Vererbung explizit angeben:
  
-<html><bottom-editor>class Animal:+<bottom-editor>class Animal:
     def __init__(self, name):     def __init__(self, name):
         self.name = name   # Attribute shared between all objects.         self.name = name   # Attribute shared between all objects.
Zeile 157: Zeile 169:
  
 for animal in [Cat("Tom"), Dog("Spike")]: for animal in [Cat("Tom"), Dog("Spike")]:
-    animal.make_sound()</bottom-editor></html>+    animal.make_sound()</bottom-editor>
          
 Wenn nicht anders angegeben, erbt eine Klasse direkt von der `object` Klasse. Diese definiert [[https://docs.python.org/3/reference/datamodel.html#basic-customization|allerhand praktische Methoden]], die wir aber _überschreiben_ können. Beispielsweise definiert die `__str__` Methode, wie ein Objekt in einen String umgewandelt wird. Dies wird von `print` benützt und gibt im Allgemeinen die Klasse und die Speicheradresse des Objekts aus: Wenn nicht anders angegeben, erbt eine Klasse direkt von der `object` Klasse. Diese definiert [[https://docs.python.org/3/reference/datamodel.html#basic-customization|allerhand praktische Methoden]], die wir aber _überschreiben_ können. Beispielsweise definiert die `__str__` Methode, wie ein Objekt in einen String umgewandelt wird. Dies wird von `print` benützt und gibt im Allgemeinen die Klasse und die Speicheradresse des Objekts aus:
  
-<html><bottom-editor>class Animal: pass+<bottom-editor>class Animal: pass
 pair = Animal() pair = Animal()
-print(pair)</bottom-editor></html>+print(pair)</bottom-editor>
  
 Überschreiben wir die `__str__` Methode, können wir bestimmen, wie Objekte in Strings umgewandelt werden: Überschreiben wir die `__str__` Methode, können wir bestimmen, wie Objekte in Strings umgewandelt werden:
  
-<html><bottom-editor>class Animal:+<bottom-editor>class Animal:
     def __init__(self, name):     def __init__(self, name):
         self.name = name   # Attribute shared between all objects.         self.name = name   # Attribute shared between all objects.
Zeile 181: Zeile 193:
  
 for animal in [Animal("Unknown"), Cat("Tom"), Dog("Spike")]: for animal in [Animal("Unknown"), Cat("Tom"), Dog("Spike")]:
-    print(animal)</bottom-editor></html> +    print(animal)</bottom-editor>
  
  
Zeile 189: Zeile 200:
 Wir möchten aufzeichnen, wie oft unsere Wörter richtig bzw. falsch übersetzt werden. Dafür benötigen wir eine `Stats`-Klasse. Neben den Attributen `correct` bzw. `incorrect` möchten wir ein Attribut `score` haben, das einen Wert zwischen `[0..1]` bereitstellt, wobei `0` bedeutet, dass das Wort noch komplett unbekannt ist, und `1`, dass das Wort perfekt gelernt wurde. Wir möchten aufzeichnen, wie oft unsere Wörter richtig bzw. falsch übersetzt werden. Dafür benötigen wir eine `Stats`-Klasse. Neben den Attributen `correct` bzw. `incorrect` möchten wir ein Attribut `score` haben, das einen Wert zwischen `[0..1]` bereitstellt, wobei `0` bedeutet, dass das Wort noch komplett unbekannt ist, und `1`, dass das Wort perfekt gelernt wurde.
  
-Die Klasse `Stats` soll eine Methode `record(correct)` erhalten: Jedes Mal, wenn ein Wortpaar getestet wird, findet der Learner heraus, ob das Wort richtig oder falsch ist. Dieses Verdikt wird mit `record()` an die Statistik weitergeleitet und dort aufgezeichnet.+Die Klasse `Stats` soll eine Methode `record(outcome)` erhalten: Jedes Mal, wenn ein Wortpaar getestet wird, findet der Learner heraus, ob das Wort richtig oder falsch ist. Dieses Verdikt oder _Outcome_ (`True` oder `False`) wird mit `record()` an die Statistik weitergeleitet und dort aufgezeichnet.
  
 Zudem sollte `Stats` auch noch eine sinnvolle `__str__` Methode haben. Zudem sollte `Stats` auch noch eine sinnvolle `__str__` Methode haben.
Zeile 203: Zeile 214:
   * Der neueste Versuch soll mehr Gewicht haben als lange zurückliegende Versuche.   * Der neueste Versuch soll mehr Gewicht haben als lange zurückliegende Versuche.
  
-Es bietet sich an, mit einem _Decay_ (_de_: Zerfall) zu arbeiten: jedes Mal, wenn ein neuer Wert dazukommt, wird der alte Score mit einem Faktor <1 multipliziert. Mit einem Faktor von 0.5 setzt sich der Score zur Hälfte aus dem neuesten Test, zur anderen Hälfte aus dem bisherigen Score zusammen: +Es bietet sich an, mit einem _Decay_ (_de_: Zerfall) zu arbeiten: jedes Mal, wenn ein neuer Wert dazukommt, wird der alte Score mit einem Faktor $\lambda < 1multipliziert, der neue Wert wird mit dem Faktor $1-\lambda$ dazu addiert. Mit einem Faktor von 0.5 setzt sich der Score zur Hälfte aus dem neuesten Test, zur anderen Hälfte aus dem bisherigen Score zusammen: 
 $$\begin{aligned} score_{new} &= 0.5 \cdot (test_0 + score_{old}) \\ $$\begin{aligned} score_{new} &= 0.5 \cdot (test_0 + score_{old}) \\
   &= 0.5 \cdot (test_0 + 0.5 \cdot (test_1 + 0.5 \cdot (test_2 + \ldots))) \\   &= 0.5 \cdot (test_0 + 0.5 \cdot (test_1 + 0.5 \cdot (test_2 + \ldots))) \\
   &= \frac{test_0}{2} + \frac{test_1}{4} + \frac{test_2}{8} + \frac{test_3}{16} + \ldots \end{aligned}$$   &= \frac{test_0}{2} + \frac{test_1}{4} + \frac{test_2}{8} + \frac{test_3}{16} + \ldots \end{aligned}$$
 +  
 +
 +##### Wilson's Plus Four
 +
 +Unser _Score_ ist mit dem Zerfall genau genommen keine Erfolgsquote mehr. Was wir eigentlich möchten: Berechnen, wie gross die Wahrscheinlichkeit ist, dass wir ein Wortpaar falsch beantworten. Genau können wir sie nicht wissen, aber wir können die Untergrenze des wahrscheinlichen Intervalls aufgrund der bisherigen Antworten abschätzen. [[wpde>Konfidenzintervall_f%C3%BCr_die_Erfolgswahrscheinlichkeit_der_Binomialverteilung|Wikipedia]] hat ein paar Ideen dazu, die [[wp>Plus_Four_Rule]] in der englischen WP zeigt einen ganz einfachen Weg: wir starten mit 2 korrekten und 2 inkorrekten Antworten (2/4 richtigen).
 +
  
  
  • talit/tutorial_oop3.1775717267.txt.gz
  • Zuletzt geändert: 2026-04-09 06:47
  • von hof