1. Kannst du mir erklären was genau du mit Datenstrucktur meinst?
2. Ich würde es gerne erstmal bei einem Vokabelbearbeitungsprogramm lassen, und jetzt erstmal die GUI implementieren damit ich das ganze endlich verstehe
3. Die Exceptions sind 1. dafür da um das Abstürtzen des Programms zu vermeiden und 2. damit die Funktion die z.B. die delete_file()-Funktion aufruft eine Rückmeldung bekommt und dem Benutzer somit mitteilen kann, dass das Löschen nicht erfolgreich war
4.Ich stelle mir das ganze zur Zeit so vor:
-Ich erstelle Klassen für die Fenster (jedes eine)
-neben der __init__ kommen da nur auf die GUI bezogene Methode rein, z.B. den Inhalt der Listbox durch einen neuen ersetzen (App.replace_listbox(neuer_inhalt))
-den Logischen Teil erledigen Funktionen außerhalb der Klassen die z.B. durch die Buttons aufgerufen werden
Wäre das denn dann richtig?
Wie kommen diese Funktion jetzt an die Instanz der Klasse?
Gruß
Easy Learn - Vokabeltrainer
-
- User
- Beiträge: 107
- Registriert: Sonntag 24. Juni 2012, 16:38
- Wohnort: Werder/Havel
Besucht mich auf http://scriptinggamer.de.cg/ 

- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
*Wie* stellst Du in Python eine "Vokabel" dar? Und wie stellst Du viele Vokabeln dar?Scriptinggamer hat geschrieben:1. Kannst du mir erklären was genau du mit Datenstrucktur meinst?
Z.B.: Wenn ich in Lateinisch "gladius" kenne und weiß, dass es auf Deutsch mit "Schwert" übersetzt wird, wie bildest Du das in Python ab? Und nun kommen da eben noch beliebig andere "Wortpaare" hinzu... wie sieht es dann aus?
Und wo liegt da nun der Gewinn, außer, dass Du nun *zusätzlich* eine gesonderte `if...else` Abfrage brauchst, in der Du sogar *weniger* Informationen über den Fehler hast als zuvor? :KScriptinggamer hat geschrieben: 3. Die Exceptions sind 1. dafür da um das Abstürtzen des Programms zu vermeiden und 2. damit die Funktion die z.B. die delete_file()-Funktion aufruft eine Rückmeldung bekommt und dem Benutzer somit mitteilen kann, dass das Löschen nicht erfolgreich war
Beispiel
Code: Alles auswählen
# Dein "Ansatz":
def func_where_excpetion_happens():
try:
# do soemthing
except SpecialException:
return False
else:
return True
def caller_func():
if func_where_exception_happens():
# keep on working
else:
# tell the user something or find workaround
# besserer Ansatz:
def func_where_excpetion_happens():
# do soemthing
def caller_func():
try:
func_where_excpetion_happens()
except SpecialException:
# tell the user *what* went wrong or find workaround
# oder auch
def func_where_excpetion_happens():
try:
# do soemthing
except SpecialException:
# find workaround
def caller_func():
# nothing can go wrong here :-)
func_where_excpetion_happens()
Code: Alles auswählen
def load(filename):
"""Diese Funktion läd aus einer JSON-Datei ein Dictionary"""
try:
with open(filename) as f:
return json.load(f)
except IOError:
# "Workaround": Wenn die Datei nicht geladen werden kann,
# dann liefern wir eben ein leeres Dictionary und das Programm
# kann weiterlaufen. (Ist natürlich nur sinnvoll, wenn ein leeres
# Dictionary weiterverarbeitet werden kann)
return dict()
def main():
adressbook = load(sys.argv[1])
# Und nun mit der Struktur weiterarbeiten:
show_adresses(adressbook)
# ... usw.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
-
- User
- Beiträge: 107
- Registriert: Sonntag 24. Juni 2012, 16:38
- Wohnort: Werder/Havel
zu 1. Ist es denn nicht ok das ich die Listen in der folgenden Form speichere: [[vokabelpaar1, vokabelpaar2, vokabelpaar3, ...], [sprache1, sprache2], Listenname] ?
zu 2. Ich werde also alle axceptions rausnehmen und später in der aufrufenden Funktionen Verwenden
Ich hab ja kein Problem damit ein Funktionierendes Programm zu schreiben, mir gehts nur darum das es auch Übersichtlich nicht vermischt und Sauber ist. Ist den meine 4. - Vorstellung ok? soll ich das erstmal umsetzen?
Gruß
zu 2. Ich werde also alle axceptions rausnehmen und später in der aufrufenden Funktionen Verwenden
Ich hab ja kein Problem damit ein Funktionierendes Programm zu schreiben, mir gehts nur darum das es auch Übersichtlich nicht vermischt und Sauber ist. Ist den meine 4. - Vorstellung ok? soll ich das erstmal umsetzen?
Gruß
Besucht mich auf http://scriptinggamer.de.cg/ 

- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Bitte noch mal genauer! Python hat doch Literale für Listen... also schreibe doch mal explizit ein Beispiel mit zwei, drei Vokabeln, damit wir das mal endlich *sehen*Scriptinggamer hat geschrieben:zu 1. Ist es denn nicht ok das ich die Listen in der folgenden Form speichere: [[vokabelpaar1, vokabelpaar2, vokabelpaar3, ...], [sprache1, sprache2], Listenname] ?

encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@Scriptinggamer: Ich finde die Form nicht okay denn in der äusseren Liste stecken Objekte mit ganz unterschiedlichen Bedeutungen, die anhand eines Indexes, also einer Zahl die überhaupt nichts über die Bedeutung aussagt, angesprochen werden. Das führt zu unnötig schwer verständlichem Quelltext mit „magischen Zahlen”.
Du solltest wie schon wiederholt gesagt vor allem erstmal eines vergessen: GUI. Und alles, was damit zu tun hat.
Und Klassen sind nichts GUI-Spezifisches!!!
Deine Datenstruktur "liste von listen mit noch was hinten dran" ist nicht wirklich gut. BlackJack hat erlauetert warum.
Man koennte da jetzt diverse Dinge machen, aber ich hab mal OO genutzt, und das hier gebaut:
Wie du siehst, habe ich den test-code gleich unten hingeschrieben. Er prueft alle Methoden ab. Und der gesamte Code kommt 100% ohne GUI oder Userinteraktion aus.
Und Klassen sind nichts GUI-Spezifisches!!!
Deine Datenstruktur "liste von listen mit noch was hinten dran" ist nicht wirklich gut. BlackJack hat erlauetert warum.
Man koennte da jetzt diverse Dinge machen, aber ich hab mal OO genutzt, und das hier gebaut:
Code: Alles auswählen
import os
from json import load, dump
from random import choice
class Vocabulary(object):
def __init__(self, learn_lang, known_lang, vocabulary=None):
self.learn_lang, self.known_lang = learn_lang, known_lang
# maps lear_lang vocabulary to known_lang answers
if vocabulary is None:
vocabulary = {}
self.vocabulary = vocabulary
def save(self, path):
name = os.path.join(path, "%s_%s.voc" % (self.learn_lang, self.known_lang))
with open(name, "wb") as outf:
dump(
{
"learn_lang" : self.learn_lang,
"known_lang" : self.known_lang,
"vocabulary" : self.vocabulary,
},
outf
)
return name
@classmethod
def load(cls, filename):
with open(filename, "rb") as inf:
d = load(inf)
return cls(d["learn_lang"], d["known_lang"], d["vocabulary"])
def __contains__(self, vocable):
return vocable in self.vocabulary
def add_vocable(self, vocable, answer):
self.vocabulary[vocable] = answer
def pick(self):
return choice(self.vocabulary.keys())
def check_answer_correct(self, learn_word, answer):
# hier koennte man in Zukunft vielleicht
# sogar eine unscharfe ueberpruefung machen,
# um tippfehler tolerant zu sein und so
return self.vocabulary.get(learn_word, "") == answer
if __name__ == "__main__":
import tempfile
import glob
voc = Vocabulary("Englisch", "Deutsch")
voc.add_vocable("fun", "spass")
voc.add_vocable("learn", "lernen")
td = tempfile.mkdtemp()
fname = voc.save(td)
voc = Vocabulary.load(fname)
assert "fun" in voc
assert "learn" in voc
assert voc.check_answer_correct("fun", "spass")
assert not voc.check_answer_correct("learn", "lesen")
assert voc.pick() in ["fun", "learn"]
-
- User
- Beiträge: 107
- Registriert: Sonntag 24. Juni 2012, 16:38
- Wohnort: Werder/Havel
Jetzige Form:
voc_list = [[["Hund", "dog", "Dogge"], ["Katze", "cat", "Kitekat"], ["Ratte", "rat", "ohne Te(e)"]], ["Deutsch", "Englisch"], "Haustierliste"}
Warscheinlich bessere Form:
voc_list = {"vocables" : [["Hund", "dog", "Dogge"], ["Katze", "cat", "Kitekat"], ["Ratte", "rat", "ohne Te(e)"]], "languages" : ["Deutsch", "Englisch"], "name" : "Haustierliste"}
Soll ich das GUI jetzt nach dem geschilderten Plan erstellen?
Gruß
voc_list = [[["Hund", "dog", "Dogge"], ["Katze", "cat", "Kitekat"], ["Ratte", "rat", "ohne Te(e)"]], ["Deutsch", "Englisch"], "Haustierliste"}
Warscheinlich bessere Form:
voc_list = {"vocables" : [["Hund", "dog", "Dogge"], ["Katze", "cat", "Kitekat"], ["Ratte", "rat", "ohne Te(e)"]], "languages" : ["Deutsch", "Englisch"], "name" : "Haustierliste"}
Soll ich das GUI jetzt nach dem geschilderten Plan erstellen?
Gruß
Besucht mich auf http://scriptinggamer.de.cg/ 

NEIN.
Sondern erstmal deine Funktionen, die auf diesen Daten arbeiten, sie laden, speichern usw. Und zwar *OHNE* globale Variablen zu benutzen!
Die Struktur halte ich immer noch nicht fuer ideal, weil sie immer noch ueber *Indizes* arbeiten. Besser waeren listen von dicts zB.
Sondern erstmal deine Funktionen, die auf diesen Daten arbeiten, sie laden, speichern usw. Und zwar *OHNE* globale Variablen zu benutzen!
Die Struktur halte ich immer noch nicht fuer ideal, weil sie immer noch ueber *Indizes* arbeiten. Besser waeren listen von dicts zB.
-
- User
- Beiträge: 107
- Registriert: Sonntag 24. Juni 2012, 16:38
- Wohnort: Werder/Havel
So,
Aber wie soll ich das jetzt mit FILES_PATH machen?
Könntest du mir ein beispiel für deine Listen-Idee geben?
Aber wie soll ich das jetzt mit FILES_PATH machen?
Könntest du mir ein beispiel für deine Listen-Idee geben?
Besucht mich auf http://scriptinggamer.de.cg/ 

Ich habe dir ein *komplettes* Beispiel fuer laden, speichern, verwalten und abfragen von Vokabeln gegeben. Hast du das nicht gesehen?!?
-
- User
- Beiträge: 107
- Registriert: Sonntag 24. Juni 2012, 16:38
- Wohnort: Werder/Havel
Oh, hab ich übersehen, danke 

Besucht mich auf http://scriptinggamer.de.cg/ 

-
- 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ß
Gruß
Besucht mich auf http://scriptinggamer.de.cg/ 

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?
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?
-
- 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.
Gruß
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")
Besucht mich auf http://scriptinggamer.de.cg/ 

- 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:
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.

@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"],
...
}

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

@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


encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@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'?
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'?
-
- 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ß
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ß
Besucht mich auf http://scriptinggamer.de.cg/ 

-
- 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?
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?
Besucht mich auf http://scriptinggamer.de.cg/ 

@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.
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.
-
- 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ß
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ß
Besucht mich auf http://scriptinggamer.de.cg/ 
