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?
- spaghetti.py
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…
- noodles.py
# 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:
- voci.py
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
undanschae
. - Füge das
.gitignore
für Python hinzu (von 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 lowercasewith_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 ANSI_escape_code