Latein Vokabel- und Grammatiktrainer

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Latein Vokabel- und Grammatiktrainer

Beitragvon klaus » Samstag 23. Juni 2007, 10:12

Hi, Leute
Ich bin neu hier auf diesem Forum und bin auch in Python noch nicht so gut und habe deshalb ein paar fragen zu meinem eigenen Latein-Vokabeltrainer:

1.Wieso ändert dieser Code die Variablen pnts (punkte) und cntr (counter)nicht ab, obwohl es eigentlich bei jeder gestellten Frage passieren sollte.

Code: Alles auswählen

## Modul-Import
from random import *

## frage-Funktion:
def frage(data):
    global pnts,cntr   
    qust, solu = data
    answ = raw_input(qust)
    if answ == solu:
        print "Richtig!"
        pnts = pnts + 1
    else:
        print "Leider falsch!"
        print "Richtig ist: ", solu
    cntr = cntr + 1
    print

## latein-Funktion:
## Begrüßung und Stoffangabe
def latein():
    print "Latein Vokabel- und Grammatiktrainer"
    print "===================================="
    print
    check1 = 0
    while check1 != 1:
        topic = raw_input("Über was möchten sie ausgefragt werden?(Vok/Grm) ")
        if topic != "Vok" and topic != "Grm":
            print "falsche Eingabe"
            print
        else:
            check1 = 1
    lek = raw_input("Welche Lektionen? ")

## Stoffzuordnung
    if topic == "Vok":
        pass
    elif topic == "Grm":
        pass
## vorl. Stoffzuordnung
    list = [("villa, ae ", "Landhaus"), ("figura, ae ", "Figur"),
            ("forma, ae ", "Gestalt"), ("Statua, ae ", "Statue"),
            ("flamma, ae ", "Feuer"), ("fabula, ae ", "Fabel")]

## Abfrage
    pnts,cntr = 0,0
    for elmt in range(3 * len(list)):
        frage(choice(list))

## Benotung
    print "Du hast",pnts,"von",cntr,"Punkten!"
    if pnts >= 0.86 * cntr:
        print "Note 1"
    elif pnts >= 0.72 * cntr:
        print "Note 2"
    elif pnts >= 0.58 * cntr:
        print "Note 3"
    elif pnts >= 0.44 * cntr:
        print "Note 4"
    elif pnts >= 0.30 * cntr:
        print "Note 5"
    else:
        print "Note 6"

## Wiederholung?
    check3 = 0
    while check3 != 1:
        rep = raw_input("Möchtest du nochmal abgefragt werden?(j/n) ")
        if rep != "j" and rep != "n":
            print "falsche Eingabe"
            print
        else:
            check3 = 1
    if rep == "j":
        print
        latein()


2.Wie kann ich es hinkriegen, dass Python mehrere Listen (z.B. lek001, lek002, lek003 bei der Benutzereingabe 1-3) zu einer Liste "list" zusammenfasst?

Wäre nett, wenn mir jemand helfen könnte, weil wenn der Code erstmal steht, werde ich wahrscheinlich meine ganzen Sommerferien damit verbringen, die Lateinvokabeln in Listen zu schreiben (über 2000 Vok.).
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Beitragvon Redprince » Samstag 23. Juni 2007, 10:52

Code: Alles auswählen

list1.extend(list2)

Und bevor du die ganzen Vokabeln abtippst, solltest du die sorgfältig Gedanken über eine passende Datenstruktur machen, sonst gibt das nur Tränen ;)
I am not part of the allesburner. I am the allesburner.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Samstag 23. Juni 2007, 12:53

Danke für die schnelle Antwort.
Allerdings weiß ich nicht, wie du das mit der sinnvollen Datenstruktur meinst. Vorerst werde ich die Vokabeln wahrscheinlich in solchen Listen speichern:
[code=][("villa, ae ", "Landhaus"), ("figura, ae ", "Figur"), ("forma, ae ", "Gestalt"), ("Statua, ae ", "Statue")][/code]
und dann entpacken:
[code=]qust, solu (frage,lösung) = tupel[/code]
Wobei ich das wahrscheinlich nur probeweise machen werde.
eigentlich habe ich vor die Voks so aufzulisten:
[code=][["villa, ae ","Landhaus",0,0],["figura, ae ","Figur",0,0][/code]
Hier werde ich dann die ersten zwei elemente einer Liste wie oben entpacken. Die beiden Nuller sind zähler, wobei die erste um 2 erhöht wird, wenn die Vokabel gewusst wurde, und um 1 erhöhe, wenn sie falsch war(die Vokabel wird ja dann richtig angezeigt und man lernt sie trotzdem gleich ein bisschen),die zweite wird gleich 1 gesetzt, wenn die Vokabel gewusst wurde.
Die Vokabel wird nicht mehr gefragt, wenn der 1. Zähler >3 und der 2. =1
ist. So wird jede Vok. mind. 2mal gefragt und wenn man sie immer falsch macht, so lange, bis sie einmal richtig war.

Außerdem habe ich den Fehler oben immer noch nicht gefunden.
fme
User
Beiträge: 34
Registriert: Sonntag 1. April 2007, 18:58
Wohnort: Bremen

Beitragvon fme » Samstag 23. Juni 2007, 12:59

Wie wäre es mit einer SQLite Datenbank?

Dort könntest du die Vokabeln am besten speichern, sortieren, filtern, etc.
Denke das da doch eine Menge Datensätzen zustande kommen werden.

Von der Datenbank aus kannst du dann die Vokabeln immer noch auslesen und in Listen & Co speichern.
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Beitragvon Redprince » Samstag 23. Juni 2007, 13:04

Zur sinnvollen Datenstruktur: Was machst du, wenn eine Vokabel mehrere Bedeutungen hat? Was machst du bei typischen Konstellationen wie et .. et? Überleg dir lieber vorher, wie du das handhaben willst, da ein späteres Ändern oftmals Ärger mit sich bringt!
I am not part of the allesburner. I am the allesburner.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Samstag 23. Juni 2007, 13:07

Mit Datenbanken habe ich noch überhaupt nicht gearbeitet und kenne mich da gar nicht aus. Wenn du mir sagst, wie des geht, dann mache ich es vielleicht (ich denke mal mit Datenbanken ist es praktischer, da man dann die Vokabeln auch noch anders verwenden kann und sie nicht fest im Skript stehen)

wenn du mir erklären könntest wie des geht, dann wäre ich sehr froh.

naja, et...et ist natürlich ne eigene Vokabel. Wenn ein Wort zwei Bedeutungen hat, wirds schwer, aber ich könnte ja dann in der Liste ein Tupel mit allen möglichen bedeutungen einfügen, des dann wieder entpackt wird und jedes element mit der Benutzereingabe verglichen wird.
Danke, das du mich darauf hingewiesen hast.

Allerdings habe ich noch ein Problem, wenn ich das ganze ohne Datenbanken mache (mit DB werde ich wahrscheinlich noch mehr haben :wink: ). Ich hätte das ganze nämlich so gemacht, dass ich eine Funktion definiere, die die ganzen listen festlegt und eine, die dann die listen zusammenfügt, allerdings müsste ich dann in der hier so benannten Funktion voklist des irgendwie hinkriegen, dass die so aufgerufen wird:
[code=]voklist(45,56)[/code]
und dass die dann die listen "list45" bis "list56" zusammenfügt, das weiß ich aber nicht wie ich des machen soll. Hier mal mein Prototyp:
[code=]def voklist(strt,fnsh):
list = []
for elmt in range(strt, fnsh + 1):
list.extend(listx)

def voklib():
list1 = []
list2 = []
list3 = []
[/code]
Aber ich kann ja nicht schreiben list.extend(list variable), oder geht des, und wenn ja, wie?
Zuletzt geändert von klaus am Samstag 23. Juni 2007, 13:25, insgesamt 1-mal geändert.
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Beitragvon Redprince » Samstag 23. Juni 2007, 13:25

Zur Einführung in das Arbeiten mit Datenbanken empfiehlt es sich wohl, ein vernünftiges Buch zu kaufen oder einige Tutorials aus dem Internet zu beziehen. Und überleg dir, was du mit Vokabeln machst, deren Bedeutung Abhängig vom Modus eines Beziehungswortes sind ;)
I am not part of the allesburner. I am the allesburner.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Samstag 23. Juni 2007, 13:28

Ich werde wahrscheinlich zwei getrennte Voks draus machen und hal einmal schreiben "Vok mit Gen." und einmal "Vok mit Dat."
oder so ähnlich.
BlackJack

Beitragvon BlackJack » Samstag 23. Juni 2007, 14:21

@klaus: Zur ersten Frage: In `frage()` werden `pnts` und `cntr` als ``global`` deklariert, in `latein()` sind sie lokal. Die Lösung ist jetzt *nicht* sie dort auch global zu machen! Vergiss am besten, dass es ``global`` gibt.

Der Zähler wird in der Funktion *grundsätzlich* um 1 hochgezählt, dass heisst das kann man auch ausserhalb der Funktion machen. Dort wo `frage()` aufgerufen wird, hast Du im Grunde schon den Zähler als `elmt` in der ``for``-Schleife.

Und `pnts` wird man in `frage()` los, indem man die Funktion zurückgeben lässt, ob die Frage richtig beantwortet wurde oder nicht. Das kann man dann auch ausserhalb der Funktion zählen.

Namen sind in Python übrigens nicht auf vier Zeichen beschränkt. Abkürzungen können zu Missverständnissen führen und soviel kürzer sind `pnts` (`points`), `cntr` (`counter`), `answ` (`answer`), `qust` (`question`) usw. auch nicht. Insbesondere bei `qust` muss man erst einmal den Quelltext verstehen um mitzubekommen, dass das `question` heissen soll. Eigentlich sollte es umgekehrt sein: Die Namen sollen einem helfen den Quelltext zu verstehen.

Die `check*`\s in `latein()` kann man loswerden, indem man eine ``while True:``-Schleife schreibt und diese mit ``break`` verlässt.

Rekursion sollte man nur für wirklich rekursive Problemlösungen verwenden und nicht um eine einfache, iterative Schleife zu modellieren.

Zur zweiten Frage: Listen kann um andere Listen entweder mit der `extend()`-Methode erweitern, oder eine neue Liste mit ``+`` erzeugen.

Statt in Listen, solltest Du die Vokabeln vielleicht lieber in Dateien speichern. Das einfachste Format dürfte CSV sein. Dafür gibt's auch ein Modul in der Standardbibliothek (`csv`).

So wie Du die Datenstruktur bisher beschreibst, stösst Du auf das Problem, dass Du über einen dynamisch generierten Namen auf die Listen zugreifen willst. Das wird in Python nicht so gerne gesehen. Die "pythonischere" Lösung wäre es, die Listen in einem Dictionary zu speichern. Also ungefähr so:

Code: Alles auswählen

all = {'lek000': [('ham', 'Schinken'), ('eggs', 'Eier')],
       'lek001': [...],
       ... }


Bei Deinem Vorschlag noch die Punkte und ein Flag bei jeder Vokabel zu speichern, solltest Du für das Flag `True` und `False` statt 1 und 0 nehmen. Das währe im Programm auch für die `check*`\s deutlicher.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Sonntag 24. Juni 2007, 10:34

Danke, du hast mir sehr geholfen BlackJack. Das mit pnts und cntr funtzt jetzt und ich habs außerhalb der Funktion frage() gemacht.
Die checks sind auch weg und durch breaks in den Schleifen ersetzt.
Mit den Namen, dass ist so eine angewohnheit von mir. Ich weiß schon, dass sie länger sein dürfen und es geht mir auch nicht um die Länge, sondern ich wähle sie meistens so, dass sie alle gleich lang sind. Is keine so gute Angewohnheit, des is mir schon selber klar, des muss ich mir mal abgewöhnen.
Wie man Listen erweitert, hat Redprince schon geschrieben, da hab ich aber noch ne frage, nämlich was ist der unterschied zwischen .extend() und .append().
Das ganze mit Dateien oder Dictionary zu machen is vielleicht einfacher, aber ich kenn mich da überhaupt noch nicht aus. Alles was ich bis jetzt über Python weiß hab ich aus dem Buch "Python 4 kids" und des hab ich auch noch nicht ganz durch. Also meine Pythonkenntnisse sind noch sehr beschränkt. Außerdem würde man doch mit dem Dictionary auch auf das Problem eines dynamischen Listen, bzw. keynamen treffen.
Die Rekursion ist vielleicht jetzt noch unnütz, da hab ich aber geplant, dass der Benutzer, wenn er "j" eingibt, nochmal über den gleichen Stoff gefragt wird, und nicht Vok/Grm und die Lektionen nochmal angeben muss. Wie man das ohne Rekursion lösen soll weiß ich nicht.
Wegen den Flags, das hab ich verwechselt, ich dachte 1 wäre "True", is mir jetzt natürlich auch klar, dass ne Zahl noch nicht zwangsläufig ein Wahrheitswert sein muss.
So, des wars erstmal, ich poste den Code vielleicht nochmal, wenn ich alles soweit ausgebessert habe, das wird aber frühestens Dienstag Nachmittag sein, weil wir nämlich am Dienstag Schulaufgabe schreiben, und jetzt ratet mal welche: Latein
BlackJack

Beitragvon BlackJack » Sonntag 24. Juni 2007, 10:43

`append()` fügt *ein* Element an eine Liste an. `extend()` erweitert die Liste um alle Elemente des angegebenen "iterables".

Code: Alles auswählen

In [10]: a = [1, 2, 3]

In [11]: a.extend([4, 5])

In [12]: a
Out[12]: [1, 2, 3, 4, 5]

In [13]: a.append([6, 7, 8])

In [14]: a
Out[14]: [1, 2, 3, 4, 5, [6, 7, 8]]


Bei einem Dictionary kann man auf die Namen direkt und einfach zugreifen. Dafür sind Dictionaries ja gerade gedacht.

Wenn man mit den gleichen Daten nochmal arbeiten möchte, macht die Rekursion noch weniger Sinn. Bei einem erneuten Aufruf arbeitet man ja auch mit neuen lokalen Namen und nicht mit den alten.

Viel Glück am Dienstag. :-)
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Sonntag 24. Juni 2007, 13:08

Danke, ein bisschen glück kann man immer brauchen.
Naja, ich hatte vor, das ganze in zwei teile zu trennen, nämlich einen für Begrüßung, Stoffangabe und die Stoffzuordnung und einen für die Abfrage und Benotung und nur den zweiten dann rekursiv zu verwenden, aber ich glaube, dass ich des jetzt auch mit einer "while 1:"-Schleife mache, die über break verlassen wird. Ist mir grad eingefallen, dass man des so machen könnte.
Übrigens, danke für die Erklärung von append.
Hier ist dann nochmal der ganze Code:

Code: Alles auswählen

##    Latein Vokabel- und Grammatiktrainer
##    ====================================
##
##    für die Bücher "Roma C I-III" und die
##    Zusatzwortschätze der "ratio"-Bücher
##    Nepos und Caesar.
##
##    Programmiert von Klaus Weidinger
##    Veröffentlicht am xx.xx.xxxx
##
##    (c) by Klaus Weidinger

## Modul-Import
from random import *
from voklib import *

## frage-Funktion:
def frage(data):
    qust, solu = data
    answ = raw_input(qust)
    if answ == solu:
        print "Richtig!"
        return 1
    else:
        print "Falsch! Richtig ist: ", solu
        return 0

## latein-Funktion:
## Begrüßung und Stoffangabe
def latein():
    print "Latein Vokabel- und Grammatiktrainer"
    print "===================================="
    print
    while 1:
        topic = raw_input("Über was möchten sie ausgefragt werden?(Vok/Grm) ")
        if topic != "Vok" and topic != "Grm":
            print "falsche Eingabe"
            print
        else:
            break
    lek = raw_input("Welche Lektionen? ")
    print

## Stoffzuordnung
    if topic == "Vok":
        pass
    elif topic == "Grm":
        pass
## vorläufige Stoffzuordnung
    list = [("villa, ae ", "Landhaus"), ("figura, ae ", "Figur"),
            ("forma, ae ", "Gestalt"), ("Statua, ae ", "Statue"),
            ("flamma, ae ", "Feuer"), ("fabula, ae ", "Fabel")]

## eventuelle Wiederholung
    while 1:
## Abfrage
        pnts,cntr = 0,0
        for elmt in range(3 * len(list)):
            corr = frage(choice(list))
            cntr = cntr + 1
            if corr == 1:
                pnts = pnts + 1
            print       

## Benotung
        print "Du hast",pnts,"von",cntr,"Punkten!"
        if pnts >= 0.86 * cntr:
            print "Note 1"
        elif pnts >= 0.72 * cntr:
            print "Note 2"
        elif pnts >= 0.58 * cntr:
            print "Note 3"
        elif pnts >= 0.44 * cntr:
            print "Note 4"
        elif pnts >= 0.30 * cntr:
            print "Note 5"
        else:
            print "Note 6"

## Wiederholung?
        while 1:
            rep = raw_input("Möchtest du diese Abfrage wiederholen?(j/n) ")
            if rep != "j" and rep != "n":
                print "falsche Eingabe"
                print
            else:
                break
        print
        if rep == "n":
            break

bei der Funktion frage() muss ich noch abändern, dass true und false zurückgegeben werden und nicht 1 und 0, weil dann kann ich mir nämlich noch die Variable corr (ob, die Frage korrekt beantwortet wurde) ersparen.
Die ganzen Variablen werde ich mal ändern, wenn ich mehr Zeit habe.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Dienstag 26. Juni 2007, 18:22

Hi Leute,

ich hab eine sachen, die mir komisch vorkommt:

1. Wieso zeigt des bei dieser Liste
[code=] list = [("villa, ae ", "Landhaus"), ("figura, ae ", "Figur"),
("forma, ae ", "Gestalt"), ("Statua, ae ", "Statue"),
("flamma, ae ", "Feuer"), ("fabula, ae ", "Fabel")][/code]
wenn ich die len()-Funktion benutze "len of unsized object" an.Und wieso zeigt es das nur an, wenn ich das Programm ausführe, nicht wenn ich die Liste in die IDLE rüberkopiere und die Funktion dann ausführe.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 26. Juni 2007, 21:52

klaus hat geschrieben:[code=] list = [("villa, ae ", "Landhaus"), ("figura, ae ", "Figur"),
("forma, ae ", "Gestalt"), ("Statua, ae ", "Statue"),
("flamma, ae ", "Feuer"), ("fabula, ae ", "Fabel")][/code]
wenn ich die len()-Funktion benutze "len of unsized object" an.

Hallo klaus!

Vielleicht hat es damit etwas zu tun, dass du "list" überschreibst. Versuche die Liste anders zu nennen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
klaus
User
Beiträge: 88
Registriert: Samstag 23. Juni 2007, 09:33
Wohnort: Kaufbeuren
Kontaktdaten:

Beitragvon klaus » Mittwoch 27. Juni 2007, 13:47

Hi, du hast recht mit dem überschreiben.
Ich hab mal ne print-anweisung eingefügt (direkt vor dem Aufruf von len) und es kam "None" raus. Allerdings wüste ich gerne, wo ich die liste überschreibe, weil ich habe mal ne print-anweisung direkt nach der Stoffzuordnung gemacht und da war die Liste genau so wie sie sein sollte, und zwischen den beiden print-Anweisungen wird die liste eigentlich nicht verändert. Jetzt such ich mal noch ein bischen wieter und hoffe, dass ich den Fehler finde und wenn nicht, dann poste ich nochmal den gesamten Quelltext (hat sich schon wieder stark verändert).

edit: hab den Fehler :D aber ich verstehe ihn nicht :cry:
hier mal der Codeteil, wo der Fehler auftritt:

[code=] print list
list = shuffle(list)
print list[/code]

Die erste print-Anweisung gibt list noch korrekt aus, die zweite schreibt None, aber wieso. Ich dachte shuffle mischt eine liste. Und hier müsste es doch "list" mischen und dann wieder der Variable "list" zuordnen, wieso ist die zweite Liste None :?:
Zumindest liegt es nicht daran, dass ich vergessenm habe random zu importieren, aber dann hätte er ja auch ne andere Fehlermeldung angezeigt.

edit2: :idea: hab rausgefunden warum:
shuffle gibt ja keinen Wert zurück, sondern mischt die liste "in place" (so stehts in der modulbibliothek). wenn ich jetzt list = shuffle(list) schreibe wird die liste erst gemischt und dann wird list der Wert None zugewiesen.
Ich muss nur shuffle(list) schreiben, dann klappts.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder