Hallo zusammen,
Ich habe aus Übungszwecke ein kleines Programm geschrieben, in welchem man die die Änderungen von Python2 zu Python3 dokumentieren kann und Begriffe über eine Suchfunktion wieder abrufen kann.
Ich habe es mal python2to3 genannt.
Hier https://gist.github.com/3143758 könnt Ihr es Euch anschauen und wenn Ihr wollt auch testen.
Sollte Euch etwas an meinem Code nicht gefallen, so freue ich mich auf ein Info.
Grüße Nobuddy
python2to3
@Nobuddy: So als Info: Der Code gefällt mir nicht. Aus Gründen die aber alle schon mehr als einmal gesagt wurden…
@Nobuddy: Es wird über die globale Variable `data` kommuniziert. Das ist eigentlich schon der Punkt wo's für die Tonne ist.
Es gibt keine echten Funktionen die Argumente entgegen nehmen und ein Ergebnis zurück geben. Die „Funktion” *die* explizit etwas zurück gibt, bei der ist das total unsinnig, denn sie gibt immer `None` zurück und das wird auch nirgends ausgewertet/verwendet.
Die Programmsteuerung über den rekursiven Aufruf von `control()` ist kaputt. So etwas macht man nicht in Programmiersprachen die in der Sprachdefinition keine optimierung von Endrekursion zusagen. Wenn das nicht von der Sprache unterstützt wird, verbraucht so ein Programm ohne Not Speicher und fährt irgendwann an die Wand wenn der Aufrufstapel voll ist.
Es gibt keine echten Funktionen die Argumente entgegen nehmen und ein Ergebnis zurück geben. Die „Funktion” *die* explizit etwas zurück gibt, bei der ist das total unsinnig, denn sie gibt immer `None` zurück und das wird auch nirgends ausgewertet/verwendet.
Die Programmsteuerung über den rekursiven Aufruf von `control()` ist kaputt. So etwas macht man nicht in Programmiersprachen die in der Sprachdefinition keine optimierung von Endrekursion zusagen. Wenn das nicht von der Sprache unterstützt wird, verbraucht so ein Programm ohne Not Speicher und fährt irgendwann an die Wand wenn der Aufrufstapel voll ist.
@BlackJack, daß ich mich noch mehr mit der Materie befassen muß ist klar und mein Code hier sich auch bestimmt anderst gestalten lässt auch!
Bei mir funktioniert es zumindest so, wie ich es mir vorgestellt habe, was aber nicht heißen soll, daß es auch so perfekt ist.
Daher würde ich mich freuen, wenn Du mich etvl. hier etwas unterstützen würdest, damit ich die Unterschiede zu meinem code erkennen kann. Soll aber nicht heißen, daß Du mir jetzt Code auf dem Präsentierteller lieferst!
Sollte 'data' Deiner Meinung, dann direkt an die jeweilige Funktion übergeben werden?
Beispiel:
Oder willst Du mir dami etwas anderes mitteilen?
Die Funktion 'datasearch()' ist für die Suchergebnisse aus der erstellten Liste, die durch die Funktion 'inputlist()' erstellt wird.
Das Einzigste was ich mir vorstellen kann, ein Argument zu übergeben, wäre die globale Variable 'data'.
Hier meine ich aber, daß hier ein erheblicher Mehraufwand an Code sich ansammeln würde.
Bei mir funktioniert es zumindest so, wie ich es mir vorgestellt habe, was aber nicht heißen soll, daß es auch so perfekt ist.
Daher würde ich mich freuen, wenn Du mich etvl. hier etwas unterstützen würdest, damit ich die Unterschiede zu meinem code erkennen kann. Soll aber nicht heißen, daß Du mir jetzt Code auf dem Präsentierteller lieferst!
'menucheck(infotext, infos)' ist hier ein interaktives Menü, welches über die globale Variable `data` kommuniziert.BlackJack hat geschrieben:@Nobuddy: Es wird über die globale Variable `data` kommuniziert. Das ist eigentlich schon der Punkt wo's für die Tonne ist.
Sollte 'data' Deiner Meinung, dann direkt an die jeweilige Funktion übergeben werden?
Beispiel:
Code: Alles auswählen
def inputlist(data):
Das dürfte wohl mit Deinem obigen Punkt zusammenhängen.BlackJack hat geschrieben:Es gibt keine echten Funktionen die Argumente entgegen nehmen und ein Ergebnis zurück geben. Die „Funktion” *die* explizit etwas zurück gibt, bei der ist das total unsinnig, denn sie gibt immer `None` zurück und das wird auch nirgends ausgewertet/verwendet.
Die Funktion 'datasearch()' ist für die Suchergebnisse aus der erstellten Liste, die durch die Funktion 'inputlist()' erstellt wird.
Das Einzigste was ich mir vorstellen kann, ein Argument zu übergeben, wäre die globale Variable 'data'.
Hier meine ich aber, daß hier ein erheblicher Mehraufwand an Code sich ansammeln würde.
Vielleicht könntest Du hier etwas genauer drauf eingehen, da mir das mit dem Aufrufstapel nicht klar ist?BlackJack hat geschrieben:Die Programmsteuerung über den rekursiven Aufruf von `control()` ist kaputt. So etwas macht man nicht in Programmiersprachen die in der Sprachdefinition keine optimierung von Endrekursion zusagen. Wenn das nicht von der Sprache unterstützt wird, verbraucht so ein Programm ohne Not Speicher und fährt irgendwann an die Wand wenn der Aufrufstapel voll ist.
Ist wohl Sommerzeit ... und alle liegen am Strand ...
Um das Sommerloch auszufüllen, habe ich mal was Neues gemacht: https://gist.github.com/3169367
Vielleicht ist das eine bessere Alternative!?
Mein Problem liegt noch bei der Namensgebung, hoffe aber das auch das halbwegs akzeptabel ist.
Um das Sommerloch auszufüllen, habe ich mal was Neues gemacht: https://gist.github.com/3169367
Vielleicht ist das eine bessere Alternative!?
Mein Problem liegt noch bei der Namensgebung, hoffe aber das auch das halbwegs akzeptabel ist.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Schön wärsNobuddy hat geschrieben:Ist wohl Sommerzeit ... und alle liegen am Strand ...
Ich verweise mal auf mein Textmenü-Tutorial - das trifft es hier zwar nicht exakt, aber da lernst Du einige Zusammenhänge bezüglich der Organisation von Daten und Funktionen. Ich denke damit könnte man da einiges aufgeräumter gestalten.
Ich gebe zu, dass ich mir das nicht sehr intensiv angeguckt habe. Allerdings sah ich ein `global` - insofern ist da noch etwas stark verbesserungsbedürftig
BTW: Die Datei `pythoninfo.txt` fehlt - bei gist.github.com kannst DU *mehrere* Dateien pro Gist hochladen. Evtl. fügst Du die noch mal nach?
Zudem sehe ich da wieder einmal eine ungewollte Rekursion - auch wenn Du das dieses Mal versuchst, via `return` zu "reparieren". Generell ist das kein schöner Ansatz und zudem vermutlich leicht zu vermeiden.
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
Ja, den Letzten beißen immer die Hunde ...
Danke für Dein Textmenü-Tutorial, dies sieht viel versprechend aus. Werde mich da mal durch arbeiten und bestimmt lässt sich mein Code aufgeräumter gestalten.
Meine Idee war, ein interaktives Menü zu erstellen, das wie eine 'Eier legende Wollmilchsau' funktioniert.
Die Funktion 'interaktiv_menu' funktioniert nach dem Prinzip, ein mehrspaltiges Auswahlmenü sowie auch ein 'Ja/nein-Menü' auszugeben und die Eingaben entsprechend zu verarbeiten. Diese Funktion funktioniert wirklich prima.
Allerdings muß ich eingestehen, daß es für einen Außen stehenden, sehr schwer ist die Funktion und der Ablauf nachzuvollziehen, was nicht sein sollte.
Ich habe eine sehr abstrakte und wahrscheinlich auch zu komplizierte Denkweise, was sich immer wieder in meinem Code wieder spiegelt.
Daher wird es für mich ein langer Weg werden, dies zu ändern und wie hier das Textmenü-Tutorial von Dir, hilft da sehr.
Schreibe weiter solche Tutorialś!
Als ich das 'global' eingesetzt habe, wußte ich daß es anderst gehen sollte, aber fehlte die zündete Idee.
Auch das mit der Rekursion, ist auch so ein Indiz, daß ich noch viel zu lernen habe.
Habe hier https://gist.github.com/3174882 nochmals die aktuelle Version mit `pythoninfo.txt`.
Danke für Dein Textmenü-Tutorial, dies sieht viel versprechend aus. Werde mich da mal durch arbeiten und bestimmt lässt sich mein Code aufgeräumter gestalten.
Meine Idee war, ein interaktives Menü zu erstellen, das wie eine 'Eier legende Wollmilchsau' funktioniert.
Die Funktion 'interaktiv_menu' funktioniert nach dem Prinzip, ein mehrspaltiges Auswahlmenü sowie auch ein 'Ja/nein-Menü' auszugeben und die Eingaben entsprechend zu verarbeiten. Diese Funktion funktioniert wirklich prima.
Allerdings muß ich eingestehen, daß es für einen Außen stehenden, sehr schwer ist die Funktion und der Ablauf nachzuvollziehen, was nicht sein sollte.
Ich habe eine sehr abstrakte und wahrscheinlich auch zu komplizierte Denkweise, was sich immer wieder in meinem Code wieder spiegelt.
Daher wird es für mich ein langer Weg werden, dies zu ändern und wie hier das Textmenü-Tutorial von Dir, hilft da sehr.
Schreibe weiter solche Tutorialś!
Als ich das 'global' eingesetzt habe, wußte ich daß es anderst gehen sollte, aber fehlte die zündete Idee.
Auch das mit der Rekursion, ist auch so ein Indiz, daß ich noch viel zu lernen habe.
Habe hier https://gist.github.com/3174882 nochmals die aktuelle Version mit `pythoninfo.txt`.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Na das hatten wir doch schon so oft. Du musst einfach das Objekt als Parameter an die anderen Funktionen weiterreichen, die auch auf dieses Objekt angewiesen sind. So einfach ist das eigentlich...Nobuddy hat geschrieben: Als ich das 'global' eingesetzt habe, wußte ich daß es anderst gehen sollte, aber fehlte die zündete Idee.
Naja, Du darfst eben nicht Funktionen wechselseitig aufrufen wie Du es bei `start` und `interactive_menu` tust! Immer wenn Du so etwas machst, erzeugst Du eine Rekursion. Stattdessen rufe einfach aus `start` nur `interactive_menu` auf und kehre von dort *immer* nach `start` zurück. Dann kann das von neuem losgehen. Das kann man in der Ausgangsfunktion prima mit einer Endlosschleife lösen:Nobuddy hat geschrieben: Auch das mit der Rekursion, ist auch so ein Indiz, daß ich noch viel zu lernen habe.
Code: Alles auswählen
while True:
# hier Aufrufe zu anderen Funktionen
# ggf. irgend eine Benutzerabfrage / spezieller Rückgabewert o.ä.,
# um mittels `break` aus der Schleife zu springen
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
Hyperion, Danke für Deine Hinweise.
Dein Textmenü-Tutorial ist wirklich Gold wert und wenn ich den Abschluß-Code betrachte, sieht das richtig schön aufgeräumt und stimmig aus. Ich werde hier eine Weile im Textmenü-Tutorial verbleiben, bis mir alles klar geworden ist.
Dann dürfte auch das Umsetzen auf mein python2to3, kein Problem mehr sein.
Dein Textmenü-Tutorial ist wirklich Gold wert und wenn ich den Abschluß-Code betrachte, sieht das richtig schön aufgeräumt und stimmig aus. Ich werde hier eine Weile im Textmenü-Tutorial verbleiben, bis mir alles klar geworden ist.
Dann dürfte auch das Umsetzen auf mein python2to3, kein Problem mehr sein.
Wobei ich bei der Endfassung des Codes aus Hyperions Tutorial in Zeile 22 ja nach wie vor über das `print("{} {}".format(index, item[0]))` stolpere. Das kann man via `print(index, item[0], sep=' ')` IMHO etwas unkomplizierter schreiben.
@snafu, ich meine daß `print("{} {}".format(index, item[0]))` bekannter und besser zu verstehen ist, für mich zumindest.
Wenn einem das `print(index, item[0], sep=' ')` geläufig ist, ist es klar kürzer.
Ich habe das Menu aus Hyperionś Textmenü-Tutorial verwendet: https://gist.github.com/3182167
Bei der Funktion handle_menu, habe ich ein try/except eingebaut. Damit kommt auch keine Fehlermeldung mehr bei Eingabe von Buchstaben oder einer leeren Enter-Eingabe.
Wenn einem das `print(index, item[0], sep=' ')` geläufig ist, ist es klar kürzer.
Ich habe das Menu aus Hyperionś Textmenü-Tutorial verwendet: https://gist.github.com/3182167
Bei der Funktion handle_menu, habe ich ein try/except eingebaut. Damit kommt auch keine Fehlermeldung mehr bei Eingabe von Buchstaben oder einer leeren Enter-Eingabe.
Code: Alles auswählen
def handle_menu(menu):
while True:
print('\n<<< Hauptmenü >>>')
for index, item in enumerate(menu, 1):
print("{} {}".format(index, item[0]))
try:
choice = int(input("Nummer: ")) - 1
if 0 <= choice < len(menu):
menu[choice][1]()
else:
print("\nBitte nur Zahlen im Bereich 1 - {} eingeben\n".format(
len(menu)))
except ValueError:
print("\nBitte nur Zahlen im Bereich 1 - {} eingeben\n".format(
len(menu)))
Code: Alles auswählen
def handle_menu(menu):
while True:
print('\n<<< Hauptmenü >>>')
for index, item in enumerate(menu, 1):
print("{} {}".format(index, item[0]))
try:
choice = int(input("Nummer: ")) - 1
menu[choice][1]()
except (ValueError, IndexError):
print("\nBitte nur Zahlen im Bereich 1 - {} eingeben\n".format(
len(menu)))
Das Leben ist wie ein Tennisball.
Du solltest dir die Änderung schon genauer anschauen. Der IndexError konnte bei dir nicht geworfen werden, ich umgehe damit nur das zusätzliche if/else. Es wäre aber insgesamt aber wohl klüger die Ausführung der Funktion aus dem try-Block zu ziehen, sonst hast du vielleicht Probleme mit Fehlern aus den Unterfunktionen, welche sich dann hübsch verstecken würden.
Code: Alles auswählen
def handle_menu(menu):
while True:
print('\n<<< Hauptmenü >>>')
for index, item in enumerate(menu, 1):
print("{} {}".format(index, item[0]))
try:
choice = int(input("Nummer: ")) - 1
func = menu[choice][1]
except (ValueError, IndexError):
print("\nBitte nur Zahlen im Bereich 1 - {} eingeben\n".format(
len(menu)))
else:
func()
Das Leben ist wie ein Tennisball.
Ich habe ein Problem mit 'globalen', das ich gerne vermeiden möchte, mir aber bisher die zündende Idee fehlt.
Als Grundlage verwende ich das Textmenü, aus dem Textmenü-Tutorial von Hyperion.
Die Funktion zum Menüpunkt 'Eintrag suchen', sieht so aus:Hoffe, es sieht nicht zu abenteuerlich für Euch aus.
Ich wollte die Ausgabe in einem bestimmten Format ausgeben. Die oberste Zeile sollte die Spaltenbenennung beinhalten. Die Ausgabezeilen mit Daten, sollten genau vertikal mit der Spaltenbenennung übereinstimmen.
Den Parameter 'nameline', habe ich bewußt global gesetzt, um später aus verschiedenen Funktionen, darauf zugreifen zu können.
Ich weiß ... 'global' ..., das stört mich selbst, aber zuerst möchte ich Euch den Zusammenhang nahe bringen!
Nun habe ich mir gedacht, daß diese Funktion 'search_entry()' auch für den Menüpunkt 'Eintrag ändern' verwendet werden kann, um doppelten Code zu vermeiden.
Dazu sieht die Funktion 'load()' zu dem Menüpunkt 'Eintrag ändern' folgendermaßen aus (ist aber noch nicht fertig!):Ich brauche (im Moment noch) die zwei 'globalś' für diese Funktion.
Nun wenn ich das richtig verstanden habe, soll Rekursion vermieden werden!
In meinem Beispiel rufe das Hauptmenü 'handle_menu(menu)' auf, wähle dort einen Menüpunkt bei der die zugehörige Funktion, einen vordefinierten Ablauf durchgeht und am Ende wieder zum Hauptmenü zurückkehrt.
Um doppelten Code zu vermeiden, nutze ich also in der Funktion 'load()', die Funktion 'search_entry()' mit und benötige aus 'search_entry()' zwei Parameter.
Wie kann ich das umsetzen, ohne wieder eine Rekursion zu verwenden?
Als Grundlage verwende ich das Textmenü, aus dem Textmenü-Tutorial von Hyperion.
Die Funktion zum Menüpunkt 'Eintrag suchen', sieht so aus:
Code: Alles auswählen
nameline = 'Nummer', 'Python2', 'Python3', 'Info'
def search_entry():
nl0 = len(nameline[1])
nl1 = len(nameline[2])
while True:
entry = input('\nSuchbegriff: ')
if entry:
print("\nEintrag wird gesucht")
with open(datapool, 'r') as infile:
reader = csv.reader(infile, delimiter="\t", quotechar="^")
global dataline
dataline = list()
r0 = set()
r1 = set()
global counter
counter = 0
for row in reader:
if row[0] == entry:
counter += 1
r0.add(len(row[0]))
r1.add(len(row[1]))
data = counter, row[0], row[1], row[2]
dataline.append(data)
elif entry in str(row):
counter += 1
r0.add(len(row[0]))
r1.add(len(row[1]))
data = counter, row[0], row[1], row[2]
dataline.append(data)
if counter == 0:
print('\nEs liegen keine Ergebnisse zu Ihrem Suchbegriff %s vor\n' % entry)
break
elif counter > 0:
print('\n-----\n{}:\t{}:{}{}:{}{}:'.format(nameline[0], nameline[1], ' ' * (4 + (max(r0) - nl0)), nameline[2], ' ' * (4 + (max(r1) - nl1)), nameline[3]))
for row in dataline:
print('{}\t{}{}{}{}{}\n'.format(row[0], row[1], ' ' * (max(r0) - len(row[1]) + 5), row[2], ' ' * (max(r1) - len(row[2]) + 5), row[3]))
print('-----')
break
Ich wollte die Ausgabe in einem bestimmten Format ausgeben. Die oberste Zeile sollte die Spaltenbenennung beinhalten. Die Ausgabezeilen mit Daten, sollten genau vertikal mit der Spaltenbenennung übereinstimmen.
Den Parameter 'nameline', habe ich bewußt global gesetzt, um später aus verschiedenen Funktionen, darauf zugreifen zu können.
Ich weiß ... 'global' ..., das stört mich selbst, aber zuerst möchte ich Euch den Zusammenhang nahe bringen!
Nun habe ich mir gedacht, daß diese Funktion 'search_entry()' auch für den Menüpunkt 'Eintrag ändern' verwendet werden kann, um doppelten Code zu vermeiden.
Dazu sieht die Funktion 'load()' zu dem Menüpunkt 'Eintrag ändern' folgendermaßen aus (ist aber noch nicht fertig!):
Code: Alles auswählen
def load():
search_entry()
while True:
try:
selection = int(input('Zeilennummer: '))
if int(1 <= selection <= counter):
for row in dataline:
if selection == row[0]:
print("\nDatensatz wird geladen\n")
chanceline = row[1:]
print(chanceline)
break
else:
print('Falsche Eingabe, bitte wählen Sie eine Zahl von 1 bis %s aus!' % counter)
except (ValueError, IndexError):
print('Falsche Eingabe, bitte wählen Sie eine Zahl von 1 bis %s aus!' % counter)
break
Nun wenn ich das richtig verstanden habe, soll Rekursion vermieden werden!
In meinem Beispiel rufe das Hauptmenü 'handle_menu(menu)' auf, wähle dort einen Menüpunkt bei der die zugehörige Funktion, einen vordefinierten Ablauf durchgeht und am Ende wieder zum Hauptmenü zurückkehrt.
Um doppelten Code zu vermeiden, nutze ich also in der Funktion 'load()', die Funktion 'search_entry()' mit und benötige aus 'search_entry()' zwei Parameter.
Wie kann ich das umsetzen, ohne wieder eine Rekursion zu verwenden?
Zuletzt geändert von Nobuddy am Freitag 27. Juli 2012, 17:39, insgesamt 1-mal geändert.
Es wurde dir doch jetzt schon mehrfach gesagt: wenn du globals hast, dann löst du diese durch Parameter bei den Funktionen und Rückgabewerte auf. Das muss man natürlich ggf. über mehrere Aufrufstufen machen. Das ist aber nun wirklich einer der Grundlagen überhaupt. Bevor das Problem nicht gelöst ist, lohnt es sich gar nicht auf deinen Code zu schauen.
Das Leben ist wie ein Tennisball.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ja, da hast Du wohl recht. Bin da noch nicht so sehr in Python3 drin gewesen... sollte ich vielleicht noch mal ändern. Oder Du änderst es direkt im wiki - größere Änderungen sind ja eigentlich nicht mehr zu erwarten und daher auch keine Konvertierung aus Github nötig.snafu hat geschrieben:Das kann man via `print(index, item[0], sep=' ')` IMHO etwas unkomplizierter schreiben.
Ich sollte auch mal mein Konverterscript in Ruby bei Github reinstellen btw...
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
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Was ist denn Dein "Hauptmenü"? Gib doch mal ein vereinfachtes Code-Fragment in dem man die Aufrufhierarchie sehen kann!Nobuddy hat geschrieben: Nun wenn ich das richtig verstanden habe, soll Rekursion vermieden werden!
In meinem Beispiel rufe das Hauptmenü 'handle_menu(menu)' auf, wähle dort einen Menüpunkt bei der die zugehörige Funktion, einen vordefinierten Ablauf durchgeht und am Ende wieder zum Hauptmenü zurückkehrt.
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