Easy Learn - Vokabeltrainer

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Oh, hab ich übersehen, danke :D
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

So, Jetzt ist das Ganze in einer Klasse und in der main() findet ein Testlauf mit abfrage (ein bisschen schlingeliges UI hat sich reingeschmuggelt) statt
Gruß
deets

warum hat sich UI eingeschmuggelt? Tests sind *TESTS*, die sollen so laufen. Ohne Interaktion. Das ist wesentlich wichtig, als da irgendwelchen User-Input einzubauen. Tests schreiben zu lernen ist deutlich wichtiger als das Beherrschen von raw_input & Co.

Und deine Datenstruktur ist immer noch murks, denn dieser rumgeindize ist unverstaendlich. Wenn du Sprachen tauschen willst, dann benutz die Sprach-Namen als Keys fuer ein Dict in den Vokablen. Dann kannst du darauf entsprechend zugreifen.

Warum hast du pickle statt json verwendet? Ein klar lesbares und sogar von Menschen schreibbares Format vs. einem opaken binaeren Blob? Gibt's dafuer einen wirklichen *Grund*?

Last but not least: FILE_PATH nicht gross, und *warum* uebrehaupt? Warum kannst du das nicht als Parameter reinreichen? UNd warum sind deine ganzen Parameter auf sinnlose default-werte ("") gestellt?
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

1. UI weil ich keinen Nutzer simulieren möchte der richtige und Falsche eingaben macht, da ist input(vokabelname) schneller geschrieben
2. Soll ich also in die Vokabelliste lauter Dictionarys mit folgendem aufbau stecken?: {"vocable1" : "Hund", "vocable2" : "dog", "crib" : "Dogge", "number" : 2}
3. Ich kenne json garnicht, in den Tutorials die ich mir angeguckt hab gabs immer nur pickle, aber wenn du sagts das es besser ist, dann ersetze ich pickle eben durch json
4. Irgendwer meinte, ich solle das in ne Variable packen damit ich es schnell ändern kann, und weil sie kontstant ist ,dachte ich mir, schreib ich sie groß...
5. Wenn ich die Parameter auf NONE stellen würde könnte es zu Fehlern kommen, so bekommt man wenn man drauf zugreift einen leeren String, und das die überhaupt auf default werte haben hat folgenden Grund: Wenn ich eine Neue Vokabelliste machen will, kann ich Name, Sprache1 und Sprache2 mitgeben. Wenn ich aber eine Vorhandene Liste öffnen will, brauche ich nur eine Instanz zu erstellen und die load Funktion ausführen.

Code: Alles auswählen

#Neue Liste:
vocabulary = Vocabulary("Englisch - Lektion 1", "Deutsch", "Englisch")
#Vorhandene Liste:
vocabulary = Vocabulary()
vocabulary.load("Haustierliste.el")
Gruß
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@1.) Nur weil Du etwas nicht willst, ist es noch lange nicht sinnvoll ;-)

@2.) Du kannst machen, wozu immer Du auch Lust hast. Aber Du solltest darüber nachdenken, ob und ggf. *wieso* eine Datenstruktur für Dich geeignet ist. Und das erkennt man eben schnell, wenn man die grundlegenden Funktionen für den Zugriff baut, denn dann merkst Du ja selber, wie einfach oder kompliziert oder gar anfällig Deine API ist.

Ich würde einzelne Vokabeln als Dictionary mit dem gegebenen Wort als Schlüssel und einer Liste von Übersetzungen als Value abbilden:

Code: Alles auswählen

vocabularies = {
    "eat": ["essen", "fressen"],
    "run": ["rennen", "laufen"],
    ...
}
Der umgekehrte Weg bedarf letztlich eines eigenen Dictionaries - Sprachen sind ja per se nicht symmetrisch bezüglich der Abbildung der Wörter ;-)

Vielleicht gibt es aber auch noch eine bessere Darstellung der Wortbeziehungen allgemein, die man ggf. für das Lernen dann in meine vorgeschlagene Form bringen kann? Auch so etwas kann man immer überlegen! Für meinen "Wer wird Millionär"-Clone habe ich die richtige Antwort auf eine Frage per Konvention und implizit in meiner persistenten Datenstruktur und weise diese erst zur Laufzeit explizit zu. Auch solche Sachen kann und sollte man sich fürhzeitig überlegen.

@3.) JSON ist nicht per se besser, sondern für viele Zwecke eben sinnvoller. Und das Eingeben / Korrigieren von Vokablen per Texteditor ist ja nun nicht so unwahrscheinlich ;-) Da greifst Du eben besser zu einem Format, welches im Klartext vorliegt.

@4.) "Irgend wer" hatte grundsätzlich natürlich recht. Sogenannte "Magic Numbers" sollte man tunlichst vermeiden - dafür kann man gerne auch mal eine globale "Konstante" einführen. In Deinem Falle bleibt die Frage, *wieso* das eine Konstante sein soll und ob es nicht *sinnvoller* ist, den Pfad als normalen Parameter zu übergeben! Zumal Du das ganze als Exemplarvariable definierst und nicht einmal als Klassenvariable. Dazu aber noch mehr beim nächsten Punkt!

@5.) Ich frage mich, ob es überhaupt so eine gute Idee ist, die Persistenz wirklich in die Vokabelklasse zu packen. Wieso kann es da nicht eine externe Funktion geben, die einem ein fertiges Exemplar der Klasse zurück liefert? Und leere Strings als default-Werte sind da einfach Unsinn. Zumal Du mit der externen Lösung so eine `init`-Funktion nicht mehr brauchst.

Ganz generell noch eine Anmerkung: Du kannst und darfst *alles* umsetzen, wie Du willst! Du musst uns nicht um Erlaubnis fragen oder gar um "Segen" bitten ;-) Wir geben einfach nur unsere Ansicht wieder - je nach User steckt dahinter aber eben eine Menge Erfahrung und Kompetenz und alleine deswegen solltest Du solche Hinweise befolgen oder wenigstens intensiv darüber nachdenken. Aber wenn Du eben gerne sofort mit GUI loslegen willst, dann darfst Du das natürlich machen :-) Du musst nur damit rechnen, dass wir Dir dann wieder vieles "um die Ohren" hauen oder schließlich keine ausführlichen Reviews mehr schreiben, wenn man keinen Lerneffekt erkennt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Scriptinggamer: Ad 1.: Tests sind dazu da dass man sie ohne Benutzerinteraktion automatisiert ausführen kann. Die sollte man einfach mal schnell ausführen können ohne dass man sich damit weiter auseinander setzen muss — wenn sie fehlerfrei durchgelaufen sind. Die kann man zum Beispiel immer aufrufen bevor man ein commit macht, um zu sehen ob die letzten Änderungen etwas am bisherigen Code kaputt gemacht haben. Wenn man dann jedes mal von Hand irgend welche zusätzlichen Eingaben machen muss, dann lässt man das testen sehr schnell bleiben weil es zu viele Umstände macht.

Ad 5.: `Vocabulary.load()` sollte dann ganz einfach keine Methode sein die man auf einem Exemplar aufruft, sondern eine `classmethod()` die man auf der Klasse aufruft und die ein `Vocabulary`-Exemplar als Rückgabewert hat.

Abfragen in beide Richtungen funktioniert IMHO nicht wirklich gut weil die beiden Seiten nicht eindeutig sein müssen. Nehmen wir mal die Liste [('Ordnung', 'order'), ('Bestellung', 'order')] und fragen nach der zweiten Sprache — was ist jetzt die korrekte Antwort auf 'order'?
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

1. Leuchtet ein, alles klar
2. Ich habe es jetzt nochmal verändert, ich finde dann ist die Datenstrucktur inordnung (So habe ich ein Objekt (dict) für jede Vokabel, mit vokabel1, 2 und Eselsbrücke) auf die ich zugreifen kann
3. Ist ja cool, so hatte ich mir das eigentlich vorgestellt mit dem Speichern von Daten...
4. Da ich es sowieso nur zwei mal nutze benutze ich halt keine Variable mehr für den Pfad
5. Wie genau sollte das dann aussehen mit dem speichern und laden?

Mir ist natürlich klar das ich machen kann was ich möchte, aber die meisten hier, vorallem die Leute die antworten, haben einfach schon viel mehr erfahrung als ich, deshalb ist es sinnvoll viel zu fragen...

Jetziges Script

Gruß
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Hi,
Was man hier nicht alles lernt, ich kannte classmethod vorher garnicht, nur von datetime.datetime.now(), aber da hab ich nicht weiter drüber nachgedacht...
Ist das denn mit der classmethod SO richtig? Gibts noch weitere Verbesserungsvorschläge?
BlackJack

@Scriptinggamer: Ja so kann man das mit einer `classmethod()` machen.

Das Abschneiden der Dateinamensendung mit ``[:-3]`` ist nicht besonders robust, weil der übergebene Dateiname auch gar keine oder eine beliebig lange Endung haben könnte. Ich würde da `os.path.splitext()` empfehlen.

Defaultwerte werden nur *einmal* ausgewertet wenn das ``def`` ausgeführt wird. Die Liste für `vocables` bei der `__init__()` gilt also für *alle* Exemplare von `Vocabulary` — was sicher nicht das Verhalten ist was gewünscht wird. Bei veränderbaren Defaultwerten sollte man also besser `None` angeben und das in der Methode dann auswerten und gegebenenfalls dort für jeden Aufruf eine neue leere Liste erstellen.

Der Name `dump_list` in `save()` wird an ein Wörterbuch gebunden. Das ist irreführend. Und ein nettes Beispiel warum man höchstens „duck types” und keine konkreten Typen als Prä- oder Suffix für Namen verwenden sollte.

Bei `add_vocable()` hätte ich erwartet das man da auch tatsächlich eine Vokabel mit konkreten Werten hinzufügen kann und nicht nur eine Platzhalterstruktur angelegt wird, die man dann extra noch füllen muss.

Man könnte auch überlegen ein paar sinnvolle „magische” Methoden zu implementieren wie `__len__()` und `__iter__()`.

`compare()` ist semantisch keine Methode. Da sollte man entweder eine Funktion draus machen, oder mit `staticmethod()` kennzeichnen, dass es keine Methode ist.

Die verschiedenen Rückgabewerte sind unschön. Und einen Teil der möglichen Ergebnisse über den Rückgabewert und einen anderen über Ausnahmen zu lösen, wäre IMHO auch unschön. Warum dort die leere Antwort als etwas anderes als einfach Falsch gewertet wird, erschliesst sich mir nicht so ganz‽ Und bei nicht ganz korrekten Antworten würde ich eher statt `True` und `False` eine Gleitkommazahl zwischen 0 und 1 als Ergebnis liefern, die irgendwie abbildet wie stark das Ergebnis abweicht. Zum Beispiel die Levenshtein-Distanz ins Verhältnis zur Länge der Eingabe(n) setzen oder so.

Warum gibt es `get_ask_list()` und `update_ask_list()`? Die machen doch sehr ähnliche Sachen. Beide haben das Problem dass der Datentyp `list` im Namen steht. Und `update_ask_list()` aktualisiert nichts — der Name ist also irreführend.

Das ``del vocabulary`` in `test_script()` ist überflüssig.
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Neue Version hier.

1. Alles was ich nicht erwähne habe ich bis auf weiteres bedingungslos akzeptiert ;)
2. Kannst du mir nochmal genau erklären warum None statt []?
3. Habe alle Typen aus den Bezeichnern genommen
4. Da ich das ganze mit GUI plane (hier die vermurkste alte GUI-Version) und man da erstmal auf einen "Neue Vokabel"-Button klickt, die leeren Felder der Listbox erscheinen, man in Entrys die Daten einträgt und auf "Eintragen" klickt, ist es nicht nötig eine neue Vokabel dierekt hinzuzufügen.
5. compare() heißt jetzt check_answer() und ist, wie auch replace_ask_vocables() (ehemaliges update_ask_list()), eine unabhängige Funktion

Vielen Dank
Gruß
BlackJack

@Scriptinggamer: Ad 2.: Die leere Liste wird nur *einmal* erstellt wenn ``def`` *ausgeführt* wird und *nicht* jedes mal wenn die Methode/Funktion *aufgerufen* wird. Das heisst alle Exemplare der Klasse teilen sich diese *eine* Liste. Hier was mit Deinem vorletzten Code passiert:

Code: Alles auswählen

In [181]: vocables = Vocabulary('test', 'Deutsch', 'English')

In [182]: vocables.add_vocable()

In [183]: vocables.change_vocable(-1, 'Papagei', 'parrot', '')

In [184]: more_vocables = Vocabulary('test', 'Spanisch', 'Italienisch')

In [185]: more_vocables.get_ask_list(0)
Out[185]: 
[{'crib': '', 'number': 0, 'vocable1': 'Papagei', 'vocable2': 'parrot'}]
Ad 4.: Es ist aber auch nicht nötig diesen unnötigen Zwischenschritt zu machen der Daten in die Datenstruktur einträgt die man dort eigentlich gar nicht haben möchte. Eine übliche GUI trägt die Daten erst ein wenn der Dialog bestätigt wurde. Wenn man den Eintrag abbricht, dann müsste man die Leerdaten auch noch wieder entfernen. Ein weiterer Arbeitsschritt den man sich sparen kann wenn man nur ausgefüllte Datensätze in die Datenstruktur übernimmt.
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Hm, ich verstehe zwar nicht genau warum sich alle Instanzen die Liste teilen würden, aber wenn sie es tun, dann ist das natürlich richtig. In meinem GUI Modell bräuchte man fürs ändern einer Vokabel: einen Klick zur auswahl der Vokabel, die 3 Einträge und den Klick auf "Eintragen",
um eine neue Vokabel zu einzutragen: einen Klick auf "Neue Vokabel", die 3 Einträge und einen Klick auf "Eintragen",
um eine Vokabel zu löschen: einen Klick auf die Vokabel, einen Klick auf "Vokabel Löschen"
und um das eintragen einer neuen Variablen abzubrechen nachdem man "Neue Vokabel" geklickt hat nur einen einzigen Klick auf löschen.

Weniger Aufwand ginge lediglich noch um einen Klick, was das ganze aber erheblich unverständlicher machen würde.

So, dann kann ich ja jetzt eigentlich mit der GUI anfangen :) ist meine folgend nochmal geschilderte Idee dafür nun inordnung?:
Jedes Fenster bekommt eine Klasse die in der __init__() den Master oder das Toplevel erstellt und mit Widgets füllt. Weitere Methoden Verwalten dann lediglich dieses Fenster. Die "Hauptarbeit" wird dann von Funktionen übernommen, die dann die Daten verarbeiten und über die Methoden der Fenster auch die GUI verwalten können.

Danke Gruß
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Scriptinggamer hat geschrieben:Hm, ich verstehe zwar nicht genau warum sich alle Instanzen die Liste teilen würden, aber wenn sie es tun, dann ist das natürlich richtig.
Dann solltest du mal http://tutorial.pocoo.org/controlflow.h ... -argumente lesen.
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Kann man sich das also so vorstellen, dass die Liste dann wie eine Klassenvariable auf der Funktion, und nicht mehr auf jedem Aufruf sitzt?
Gruß
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, aber das solltest du nicht, denn das Prinzip ist viel genereller: Funktionen sind wie alles andere auch Objekte, d.h. sie sind mit Speicher verknuepft, in dem Fall werden die Defaults auch direkt auf dem Funktionsobjekt gespeichert:

Code: Alles auswählen

In [1]: def foo(bar=[]):
    bar.append(42)
   ...:     

In [2]: foo.func_defaults
Out[2]: ([],)

In [3]: foo()

In [4]: foo.func_defaults
Out[4]: ([42],)

In [5]: foo()

In [6]: foo.func_defaults
Out[6]: ([42, 42],)
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Hallo,
Ich habe jetzt erstmal das Verwaltungsfenster eingebaut, mit einer Funktion zum Listen Löschen (sonst nichts).
Neustes Commit hier inwieweit ist das Ok?
Gruß
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Deine Fenster habe ich mich jetzt nicht angeguckt, aber das API von Deiner Vokabelklasse ist ja (immer noch) grauenhaft:

Code: Alles auswählen

    def add_vocable(self):
        self.vocables.append({"vocable1" : "",
                              "vocable2" : "",
                              "crib" : ""})

    def change_vocable(self, index, vocable1, vocable2, crib):
        self.vocables[index] = {"vocable1" : vocable1,
                                "vocable2" : vocable2,
                                "crib" : crib}

# und dann zum Benutzen:
    vocabulary.add_vocable()
    vocabulary.change_vocable(0, "Hund", "dog", "Dogge")
    vocabulary.add_vocable()
    vocabulary.change_vocable(1, "Katze", "cat", "Kitekat")
    vocabulary.add_vocable()
    vocabulary.change_vocable(2, "Ratte", "rat", "ohne te(e)")
Das musst Du doch selber sehen, wie umständlich Du das gelöst hast!
Wieso kann `add_vocable` nicht die Argumente direkt aufnehmen? Und Dein `change_vocable` könnte doch dann einfach `delete_vocable` und `add_vocable` nutzen!

Zudem verstehe ich immer noch nicht, wieso Du das als Liste von Dictionaries ablegst. Wesentlich einfacher wäre es imho immer noch, das ganze als Dictionary anzulegen. Wenn Du darin Übersetzung(en) und Hinweiswort flexibel organisieren willst, dann nutze eben als Wert ein weiteres Dictionaries mit fixen Keys:

Code: Alles auswählen

vocabularies = {
    "eat" : {
        "translations": ["essen", "fressen"],
        "mnemonic": "Nicht trinken, sondern..."
    },
    "walk": { ... },
    ...
}
Wenn man wirklich mit solchen Zusatzinformationen arbeiten will, dann würde ich mir fast überlegen, eine einzelne Vokabel noch in einer Klasse zu modellieren.

Auf jeden Fall ist deine jetzige Form ziemlich umständlich.

Ein Index als Zugriff auf eine Vokabel ist an sich auch schon keine gute Idee, da sich bei Änderungen der Reihenfolge ggf. Abhängigkeiten verschieben! Bedenke doch mal, Du willst später mal "Lektionen" einführen, also Sammlungen von Vokabeln. Bei Deinem Ansatz wäre das so etwas wie eine Liste von Indizes:

Code: Alles auswählen

lesson = [0, 1, 2, 6, 10, 22, 34]
Nun musst Du beim Löschen einer Vokabel aufpassen, dass Du die Referenz auch aus der Lektion heraus nimmst, da sich ansonsten alle anderen Referenzen ja verschöben. Nehmen wir an, dass die Vokabel mit dem Index 6 gelöscht würde, dann würden nun die restlichen Vokabeln 10, 22 und 34 auf eine andere Vokabl verweisen, nämlich die bis dato jeweils danach kommende.

Würdest Du das Wort als Schlüssel nutzen, dann könntest Du bei der Lektion diesen einfach nutzen. Damit musst Du zwar aufpassen, ob das Wort noch existiert (`KeyError` kann man leicht abfangen und dazu nutzen!), aber alle *anderen* Wörter bleiben Dir genau so erhalten.

Weiterhin fiel mir noch dieses Konstrukt auf:

Code: Alles auswählen

            deleted = True
            for file_index in selection:
                try:
                    os.remove(os.path.join("vocabulary",
                                           mainwindow.files[file_index]))
                except WindowsError:
                    deleted = False
            if deleted:
                msg.showinfo(title = "Erfolgreich gelöscht",
                message = "Die ausgewählten Listen wurden erfolgreich gelöscht")
            else:
                msg.showinfo(title = "Fehler",
                         message = "Beim Löschen ist ein Fehler aufgetreten")
Das ist doch auch wieder so eine unnötige Sache! Wozu brauchst Du `deleted`? Doch nur, um *außerhalb* des `try...except`-Konstruktes nachträglich zu gucken, ob eine Ausnahme passiert ist oder nicht. Stattdessen kannst Du Dir das doch komplett sparen und die Aktionen eben *in* den Block reinziehen:

Code: Alles auswählen

            for file_index in selection:
                try:
                    os.remove(os.path.join("vocabulary",
                                           mainwindow.files[file_index]))
                    msg.showinfo(title = "Erfolgreich gelöscht",
                    message = "Die ausgewählten Listen wurden erfolgreich gelöscht")
                except WindowsError:
                    msg.showinfo(title = "Fehler",
                         message = "Beim Löschen ist ein Fehler aufgetreten")
Generell würde ich mir noch mal mehr Gedanken zu meiner Datenstruktur machen, bevor ich an der GUI weiterarbeiten würde. Und solltest Du nun noch daran etwas ändern, hast Du bestimmt einige Mühe beim Refactorn Deines GUI-Codes... und genau deswegen lohnt es sich, das im Vorfeld möglichst gut zu durchdenken ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Das ist alles immer noch murks. Hyperion hat ja schon eine Menge richtiges zu deinem immer noch falschen Ansatz ueber eine Liste gesagt.

Und ich habe dir vorgeschlagen, die *Sprache* als Schluessel zu benutzen. Also zb

Code: Alles auswählen

{ "deutsch" : "pferd", "englisch" : "horse" }
Dann brauchst du nicht deine Daten umzustrukturieren, nur weil du deutsch->englisch oder englisch->deutsch "umschaltest".

Aber dein "language1" "language2" -Kram ist einfach nur ein dictionary mit durchnummerierten Schluesseln - da kannst du auch bei deiner Liste bleiben, das aendert ja nix.

check_answer gibt "false" zurueck - das ist natuerlich auch nicht richtig, sondern muesste False (ohne Anfuehrungszeichen) sein. Und "upperLower" solltest du dir sparen, sondern gleich True zureckgeben, weil du es immer normalisiert vergleichen solltest.

Ausserdem sollte das IMHO eine Methode von Vocabulary sein, (welches immer noch keine new-style Klasse ist, das hatte BlackJack schon vor diversen Posts erwaehnt). Denn nur so kannst du dann zB die entsprechende Vokabel spaeter mal markieren als "richtig beantwortet", und die Wahrscheinlichkeit dafuer, dass sie beantwortet werden muss, reduzieren. So, wie gute Vokabeltraiener das machen.

Auch die mehrfachen shuffles/asks/replaces und so sind alle unnoetig. Einmal reicht.

Und das ewige rumgefuhrwerke mit "vocabulary" als Pfad ist auch unnoetig. Ein Vocabulary-Objekt sollte seinen vollen Pfad kennen, um sich selbst laden, speichern und loeschen zu koennen.

Last but not least solltest du die GUI in ein *extra* Modul packen, damit du dann getrennt testen und GUI starten kannst.
deets

Und noch ein kleiner Nachtrag:

Code: Alles auswählen


  if vocables == None:
            self.vocables = []
        else:
            self.vocables = vocables
Das ist ebenfalls nicht ideal. Zum einen sollten Vergleiche mit None mit "is" stattfinden, da None ein Singleton ist, und auf Objektidentitaet geprueft werden sollte. Das macht halt der is-Operator.

Zum anderen wuerde ich das kompakter schreiben:

Code: Alles auswählen

if vocables is None:
   vocables = []
self.vocables = vocables
Damit hast du den kompletten else-Zweig gespart, was von Vorteil ist da nun ein Betrachter (im Zweifel du selbst in 3 Wochen) weniger verstehen muss, was da vor sich geht.
Scriptinggamer
User
Beiträge: 107
Registriert: Sonntag 24. Juni 2012, 16:38
Wohnort: Werder/Havel

Hi,
-Ich könnte es folgender maßen machen:

Code: Alles auswählen

{"vocables" : [{"Deutsch" : ["hallo", "guten Tag", "hi"], "Englisch" : ["hello", "hi"]},
                   {"Deutsch" : ["Hund"], "Englisch" : ["dog"]}],
"languages" : ["Deutsch", "Englisch"]}
Das wäre zwar wieder in einer liste, aber es würde mehrere übersetzungen erlauben, in beiden Richtungen. Ich könnte ja ein Dictionary weder geordnet, noch geshuffelt benutzen, oder geht das irgendwie? ich könnte höchstens noch eine liste mit den key's erstellen, über die dann das dictionary angesprochen wird, aber das ist ja doof.
-Und ich könnte dann eben einfach die Sprachen umdrehen und damit die Abfragerichtung, nach deets Idee.
-Aber ich sollte doch nicht nur Richtig und Falsch benutzen, jetzt auf einmal doch? Soll ich dann erst für den Richtig-/Falsch-Dialog überprüfen was genau der Fehler ist?
-Was ist eine "new-style Klasse"?
-Naja das get_ask_vocables gibt erstmal eine liste zum Abfragen zurück, und das replace_ask_vocables shuffelt sie und sortiert aus, wie sollte das eine Funktion machen?
-das mit dem Pfad klingt gut
-Aber wenn ich es später cz_freezen will, muss dann nicht alles in einem script sein?
-Beim Löschen will ich ja nicht nach jeder Datei eine Meldung sondern erst wenn alle durch sind.
-Da ich immer direkt aus der Liste lösche, und dann die Listbox update, ist das mit den Indizes auch kein problem

Gruß
Antworten