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 [2025-05-11 15:00] – [Aufgabe C: Bessere Auswahlstrategien] hoftalit:tutorial_oop3 [2025-05-26 14:11] (aktuell) – [Aufgabe F] hof
Zeile 227: Zeile 227:
 </code> </code>
  
-### Refactoring+## Refactoring
  
 Dein Code in `ConsoleLearner.learn()` könnte irgendwie so aussehen: Dein Code in `ConsoleLearner.learn()` könnte irgendwie so aussehen:
Zeile 244: Zeile 244:
  
 Wir möchten einige Teile dieses Verhaltens anpassen: Wir möchten einige Teile dieses Verhaltens anpassen:
-#### Auswahl eines Wortes+### Auswahl eines Wortes
 Statt immer alle Paare durchzugehen, möchten wir andere Auswahl-Strategien ermöglichen: Statt immer alle Paare durchzugehen, möchten wir andere Auswahl-Strategien ermöglichen:
   * zufällige Wahl eines Wortpaars   * zufällige Wahl eines Wortpaars
Zeile 252: Zeile 252:
  
 <code python> <code python>
-class SelectionStrategy:+class LearningStrategy:
     def select(self, unit):     def select(self, unit):
         pass  # has to be implemented by subclasses.         pass  # has to be implemented by subclasses.
 </code> </code>
  
-Hier ein Beispiel für das lineare durchgehen der Paare:+Hier ein Beispiel für das lineare Durchgehen der Paare, wie im ursprünglichen Code:
  
 <code python> <code python>
-class LinearStrategy:+class LinearStrategy(LearningStrategy):
     """A learning strategy that selects all word pairs in a unit, in order."""     """A learning strategy that selects all word pairs in a unit, in order."""
     def __init__(self):     def __init__(self):
Zeile 274: Zeile 274:
  
 <code python> <code python>
-   def learn(self, unit, selection_strategy=LinearStrategy()):+   def learn(self, unit, learning_strategy=LinearStrategy()):
         for _ in range(len(unit.pairs)):         for _ in range(len(unit.pairs)):
-            pair = selection_strategy.select(unit)+            pair = learning_strategy.select(unit)
             guess = input(f'Translate {pair.word1}')             guess = input(f'Translate {pair.word1}')
             correct = guess == pair.word2             correct = guess == pair.word2
Zeile 285: Zeile 285:
                 print(f'Incorrect, {pair.word1} translates to {pair.word2}')                 print(f'Incorrect, {pair.word1} translates to {pair.word2}')
 </code> </code>
 +
 ### Aufgabe C: Bessere Auswahlstrategien ### Aufgabe C: Bessere Auswahlstrategien
 Schreibe zwei Auswahl-Strategien mit folgenden Eigenschaften, und teste sie aus. Schreibe zwei Auswahl-Strategien mit folgenden Eigenschaften, und teste sie aus.
Zeile 293: Zeile 294:
  
 Du hast damit das [[wp>Strategy_pattern|Strategie-Entwurfsmuster]] kennengelernt. Du hast damit das [[wp>Strategy_pattern|Strategie-Entwurfsmuster]] kennengelernt.
- 
 ### Aufgabe D: Wie lange lernen? ### Aufgabe D: Wie lange lernen?
 Ähnlich wie die Entscheidung über das nächste Wortpaar möchten wir auch die Entscheidung, wie lange gelernt werden soll, abstrahieren. Ähnlich wie die Entscheidung über das nächste Wortpaar möchten wir auch die Entscheidung, wie lange gelernt werden soll, abstrahieren.
  
-Schreibe eine Klasse `StopCriterion`  mit einer Methode `should_stop(self, unit)`. Implementiere verschiedenen Kriterien, zum Beispiel:+Schreibe eine Klasse `StopCriterion`  mit einer Methode `should_stop(self, unit)`. Implementiere verschiedenen Kriterien als Unterklassen von `StopCriterion`, zum Beispiel: 
 + 
 +  * `ScoreCriterion`: stoppt, wenn der Score des schlechtesten WortPaars über 90% (oder einem konfigurierbaren Wert) liegt. 
 +  * `TimeCriterion`: stoppt, wenn eine definierte Zeit verstrichen ist. 
 +  * `CountingCriterion`: stoppt nach einer definierten Anzahl Wortpaare. 
 +  * `OrCriterion`: kombiniert mehrere Kriterien, stoppt, wenn mindestens eines der Kriterien stoppt. 
 + 
 +{{:talit:tutorial_oop3:pasted:20250513-173205.png?nolink&400}} 
 + 
 +Wie sieht die `ConsoleLearner.learn` Methode jetzt aus? 
 +## Speichern & Lesen 
 +Wir möchten `VocabularyUnits` in eine Datei speichern und von dort wieder lesen können. Es bietet sich an, eine Unit als JSON-Objekt zu speichern. JSON (JavaScript Object Notation) sind Dictionaries, die als Keys nur Strings, als Werte ausschliesslich Strings, Zahlen, Boolean-Werte, Listen und wiederum JSON-Objekte enthalten. Ein `WordPair` könnte zum Beispiel so aussehen: 
 + 
 +<code python> 
 +{"word1": "Baum", "word2": "tree", "correct": 26, "incorrect": 4, "score": 0.9999961480498314} 
 +</code> 
 + 
 +Eine ganze Unit wäre dann eine Liste solcher Objekte: 
 + 
 +<code python> 
 +
 +  { 
 +    "word1": "Baum", 
 +    "word2": "tree", 
 +    "correct": 24, 
 +    "incorrect": 4, 
 +    "score": 0.9249845921993256 
 +  }, 
 +  { 
 +    "word1": "Blume", 
 +    "word2": "flower", 
 +    "correct": 30, 
 +    "incorrect": 14, 
 +    "score": 0.9999847523718017 
 +  } 
 +
 +</code> 
 +### Aufgabe E: JSON-Serialisierung 
 + 
 +  * Füge eine Methode `to_dict(self)` zu `WordPair` hinzu, die ein Wort-Paar und seine Stats in ein Dictionary verwandelt und zurückgibt. 
 +  * Füge eine Methode `save_to(self, filename)` zu `VocabularyUnit` hinzu, die die ganze Unit in die angegebene Datei speichert, in dem alle Wort-Paar-Dictionaries in eine Liste eingefügt werden. Diese kann dann mit [[https://docs.python.org/3/library/json.html#basic-usage|json.dump]] in eine Datei geschrieben werden: 
 + 
 +<code python> 
 +    def save_to(self, filename): 
 +        json_list = [pair.to_dict() for pair in self.pairs] 
 +        import json 
 +        with open(filename, 'w') as out: 
 +            json.dump(json_list, out, indent=2)  # indent=2 aligns the output nicely 
 +</code> 
 + 
 + 
 +### Statische Methoden 
 +Fürs Einlesen kommt die umgekehrte `json.load` Funktion zum Einsatz. Allerdings haben wir noch ein kleines Problem: Eine VocabularyUnit existiert ja noch gar nicht, wenn wir sie einlesen wollen aus der Datei. Wir benötigen also eine Funktion, die nicht an eine bestimmte Unit gebunden ist. Diese werden mit `@staticmethod` annotiert und haben keinen `self` Parameter. Statische Funktionen werden direkt über den Klassennamen aufgerufen. 
 + 
 +<code python> 
 +class WordPair: 
 +    ... 
 +     
 +    @staticmethod 
 +    def from_dict(data): 
 +        """Creates a fresh word pair from json data.""" 
 +        pair = WordPair(data['word1'], data['word2']) 
 +        # TODO also read stats if available 
 + 
 + 
 +class VocabularyUnit: 
 +    ... 
 +     
 +    @staticmethod 
 +    def read_from(filename): 
 +        """Reads a vocabulary unit from a file.""" 
 +        import json 
 +        pairs = [] 
 +        with open(filename, 'r') as infile: 
 +            json_pairs = json.load(infile) 
 +            pairs = [WordPair.from_dict(p) for p in json_pairs] 
 +            return VocabularyUnit(pairs) 
 +</code> 
 +### Aufgabe F 
 +Füge statische Methoden zu `VocabularyUnit` und `WordPair` hinzu, um die gespeicherten Daten wieder einlesen zu können. 
 + 
 +Ein Beispielprogramm für unseren Code könnte nun so aussehen: 
 + 
 +<code python> 
 +from voci import * 
 + 
 +filename = 'data/test.voci' 
 +unit = VocabularyUnit.read_from(filename) 
 + 
 +learner = ConsoleLearner() 
 +try: 
 +    learner.learn(unit) 
 +    unit.print_stats() 
 +finally:   # Code im finally-Block wird jedenfalls ausgeführt, auch wenn eine Exception passiert ist. 
 +    unit.save_to(filename) 
 +</code> 
  
-  * `ScoreCriterion`: lernt solange, wie der Score des schlechtesten WortPaars unter 90% (oder einem konfigurierbaren Wert) liegt. +### Aufgabe G - Webapp 
-  * `TimeCriterion`: lernt solange, bis eine definierte Zeit verstrichen ist. +Sauch [[talit:flask_webserver]] und [[ef_informatik:webapps:start]].
-  * `CountingCriterion`lernt eine definierte Anzahl Wortpaare. +
-  * `OrCriterion`kombiniert mehrere Kriterien, lernt solange, bis eines der kombinierten Kriterien stoppt.+
  • talit/tutorial_oop3.1746975631.txt.gz
  • Zuletzt geändert: 2025-05-11 15:00
  • von hof