# Objekt-orientierte Programmierung 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? v = [ [["Baum", "tree"], 0, 0], [["Blume", "flower"], 0, 0], [["Fisch", "fish"], 0, 0], ] for _ in range(3): for w in v: w1, w2 = w[0] if w2 == input(f"Translate {w1}: "): w[1]+=1 print("correct") else: w[2]+=1 print("incorrect") for w in v: print(f'{w[1]/(w[1]+w[2]):.0%}: {w[0]}') Code wird nur einmal geschrieben, aber sehr viel häufiger und von mehr Personen gelesen. Es lohnt sich also, in leserlichen Code zu investieren. Natürlich könnten wir obigen _Spaghetti-Code_ mit besseren Variablennamen, Dictionaries und Kommentaren verbessern. Nur verlieren wir vor lauter Strings schnell den Überblick... # Define vocabulary unit voci_unit = [ {'translation': {'word1':"Baum", 'word2': "tree"}, 'correct': 0, 'incorrect': 0}, {'translation': {'word1':"Blume", 'word2': "flower"}, 'correct': 0, 'incorrect': 0}, {'translation': {'word1':"Fisch", 'word2': "fish"}, 'correct': 0, 'incorrect': 0}, ] # Make three passes for _ in range(3): for w in voci_unit: if w['translation']['word2'] == input(f"Translate {w['translation']['word1']}: "): w['correct']+=1 print("correct") else: w['incorrect']+=1 print("incorrect") # Print statistics for w in voci_unit: print(f'{w['correct']/(w['correct']+w['incorrect']):.0%}: {w['translation']}') Wouldn't it be nice... wenn wir unsere Lernprogramm ohne viel Kommentar und trotzdem kurz und verständlich definieren könnten? Zum Beispiel so: from voci import * unit = VocabularyUnit([ WordPair('Baum', 'tree'), WordPair('Blume', 'flower'), WordPair('Fisch', 'fish') ]) learner = ConsoleLearner() learner.learn(unit) unit.print_stats() ## Klassen und Objekte Genau das erreichen wir mit der **objekt-orientierten Programmierung**. Du hast bereits sehr oft Objekte benutzt, zum Beispiel Strings oder Listen. Ein Objekt gruppiert Attribute (en. _attributes_) und Methoden (Funktionen, die zum Objekt gehören). Alle Objekte einer _Klasse_ haben die gleichen Methoden und die gleichen Attribut-Namen, aber möglicherweise unterschiedliche Inhalte in den Attributen. **Beispiel**: Alle Listen-Objekte enthalten eine Sequenz von Elementen, aber nicht dieselben. Die `pop`-Methode wird aber für alle Listen-Objekte das letzte Element entfernen und zurückgeben. Eine Klasse wird in Python mit dem `class` Keyword definiert. Methoden haben immer einen ersten Paramter `self`, der für das konkrete Objekt steht, für das die Methode ausgeführt wird. Wird eine neues Objekt erstellt, wird zuerst die `__init__` Methode aufgerufen. Am bestem am Beispiel: class WordPair: """A word and its translation.""" def __init__(self, word1, word2): """Creates a new pair from two strings.""" self.word1 = word1 # All objects of class WordPair share the same attributes self.word2 = word2 # but not necessarily the same contents. def reversed(self): # All objects of class WordPair share the same methods """Returns a copy of the pair in the reverse direction.""" return WordPair(self.word2, self.word1) tree = WordPair('Baum', 'tree') # we are passing only two arguments, the self argument is implicit. print(f'{tree.word1} translates to {tree.word2}') # Attributes can be accessed using dot-notation. ### Aufgabe A * Erstelle ein neues github-Repository `ksr_talit_vocabulary` und clone es lokal in VS Code. * Teile es mit `tkilla77` und `anschae`. * Füge das `.gitignore` für Python hinzu (von [[https://github.com/github/gitignore/blob/main/Python.gitignore|hier]]). Erstelle eine neue Python-Datei `voci.py` und erstelle deine erste Klasse `WordPair` wie oben und zeige sie der Lehrperson. Achte auf: * Coding-Conventions: * Klassennamen in CamelCase * Methoden und Attribute in lower_case_with_underscores() * Dokumentation mit `"""doc strings"""` Wir möchten zusätzlich eine Klasse `VocabularyUnit` haben, die eine Liste von `WordPairs` speichert. Als drittes benötigen wir eine Klasse `ConsoleLearner` mit einer Methode `learn(unit)`, die alle WortPaare abfragt. * um das Terminal zu leeren kannst du `print("\033c", end="")` benützen * um die Zeile im Terminal zu löschen, verwendest du `print("\033[H\033[J", end="")` * mehr dazu auf [[wp>ANSI_escape_code]]