@Gödel: Die am Anfang definierten Werte für `i` und `j` werden nirgends verwendet, die Defintionen machen also keinen Sinn und können weg. Das gilt auch für das ``i = 0`` vor der Abfrageschleife.
`data_list` und `data_dic` werden zu früh definiert. Man definiert Namen erst wenn sie gebraucht werden, und nicht alle am Anfang. Das macht es schwieriger den Code zu verstehen wenn man bei der ersten Verwendung eines Namens erst wieder am Anfang suchen muss, wie der definiert wurde. Wenn das Programm grösser wird und man viel am Anfang ”auf Vorrat” definiert hat, übersieht man gerne mal unbenutzte Namen, die entweder gar nicht oder nach Überarbeitung weiter unten im Code nicht mehr verwendet werden. Es ist auch aufwändiger Code aus einer Funktion die zu gross geworden ist, in kleinere Funktionen heraus zu ziehen, wenn man sich den Code erst zusammensuchen muss, wenn Code der eigentlich zusammengehört nicht in zusammenhängenden Zeilen steht.
Grunddatentypen haben in Namen nichts zu suchen. Der Leser will in der Regel nicht wissen ob er eine Liste oder ein Wörterbuch vor sich hat, sondern was die Werte darin bedeuten. Also `data_list` wäre beispielsweise `rows` und `data_dic` beispielsweise `english_to_german`.
Dateien sollte man wo möglich mit der ``with``-Anweisung vewenden, damit sie garantiert wieder geschlossen werden, wenn der ``with``-Block verlassen wird. Das schliessen steht momentan auch an einer etwas unerwarteten Stelle weil Leerzeilen so etwas wie zusammenhängende Schritte trennen. Und der erste Zeilenblock wäre „Daten einlesen“ und der zweite „Vokabeln abfragen“ und da würde das Schliessen der Datei zum einlesen gehören und nicht zum abfragen.
Bei Textdateien sollte man immer explizit die Kodierung beim öffnen angeben, sonst verhält sich das Programm bei unterschiedlichen Systemen anders. Wenn man die Kodierung selbst in der Hand hat, würde ich UTF-8 wählen, falls es keinen sinnvollen Grund für etwas anderes gibt.
Das `csv`-Modul erwartet das Dateien mit dem Argument ``newline=""`` geöffnet werden. Siehe Dokumentation.
Eine leere Liste erstellen und dann in einer Schleife die Elemente aus einem iterierbaren Objekt anzuhängen ist unnötig umständlich. Da ruft man einfach `list()` mit dem iterierbaren Objekt auf:
Code: Alles auswählen
rows = []
for row in csv.reader(file):
rows.append(row)
# =>
rows = list(csv.reader(file))
Beim füllen des Wörterbuchs ist die innere Schleife unsinnig. Die läuft immer zwei mal, einmal mit j=0 und einmal mit j=1, aber nur wenn `j` den Wert 1 hat wird überhaupt etwas gemacht, das heisst es braucht da überhaupt gar keine Schleife und auch kein `j` weil man ja weiss, dass das 1 ist und j-1 dann 0 ist und man direkt die Zahlwerte dort hinschreiben könnte:
Code: Alles auswählen
for j in range(0, 2):
if j == 1:
english_to_german[rows[i][j - 1]] = rows[i][j]
# =>
english_to_german[rows[i][0]] = rows[i][1]
Code der Art ``for i in range(len(sequence)):`` ist in Python ein „anti pattern“ weil man direkt über die Elemente von `sequence` iterieren kann, ohne den Umweg über einen Laufindex. Also:
Code: Alles auswählen
for i in range(len(rows)):
english_to_german[rows[i][0]] = rows[i][1]
# =>
for row in rows:
english_to_german[row[0]] = row[1]
Aber auch bei `row` braucht man keinen Indexzugriff, weil man schon beim iterieren die beiden Werte an sinnvolle Namen binden kann:
Code: Alles auswählen
for row in rows:
english_to_german[row[0]] = row[1]
# =>
for english, german in rows:
english_to_german[english] = german
Aber es geht noch einfach, denn genau wie `list()` ein iterierbares Objekt mit Elementen entgegen nimmt, kann man `dict()` ein iterierbares Objekt mit Schlüssel/Wert-Paaren übergeben, also in diesem Fall einfach `rows`. Und das muss auch keine Liste sein, die man danach ja sowieso nicht mehr braucht, sondern man kann da auch gleich das Reader-Objekt übergeben.
Auch bei der Abfrageschleife ist der Index wieder unnötig, und das hier immer noch die Liste verwendet wird, obwohl alle Informationen auch im Wörterbuch stecken ist redundant und damit im Grunde falsch.
In der Schleife braucht man immer zusammengehörige Schlüssel/Wert-Paare, also das was die `items()`-Methde auf Wörterbüchern liefert. Oder, da hier nirgends ein Zugriff über den Schlüssel erforderlich ist, speichert man es einfach in einer Liste.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import csv
def main():
with open("Vocabeln.txt", "r", encoding="utf-8", newline="") as file:
translations = list(csv.reader(file))
for english, german in translations:
user_input = input(f"{english}. What´s the german word?\n>")
if user_input == german:
print("Correct")
else:
print("Wrong! Correct word:", german)
if __name__ == "__main__":
main()
Man müsste die Daten noch nicht einmal in einer Liste speichern, weil man die ``for``-Schleife auch direkt über das Reader-Objekt laufen lassen könnte.