Tutorial: Einfache Textmenüs mit Python

Gute Links und Tutorials könnt ihr hier posten.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

snafu hat geschrieben: Nee, hab ich nicht. :oops:
Da muss ich immer hieran denken: Link :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Hyperion hat geschrieben:Es sind sicherlich noch einige Fehler darin enthalten, daher würde ich mich über "Debug"-Hilfe freuen :-)
Das Ding ist gut. Richtig gut.

Nur gegenüber

Code: Alles auswählen

if choice in range(len(menu)):
würde ich

Code: Alles auswählen

if 0 <= choice < len(menu):
bevorzugen.

*edit* Ich hatte vorher einen Fehler gesehen wo keiner war.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@me: Danke. Ich habe die Überprüfung auf Deinen Vorschlag umgestellt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Hyperion hat geschrieben:Danke für die Kritik :-)
@frabron: Wie würdest Du denn begründen, dass man diesen Anti-Pattern nicht verwenden sollte? Ich dachte die nachfolgende Darstellung würde ausreichen. Aber vielleicht muss da tatsächlich mehr "Kausalität" rein.
Meiner Meinung nach kommt die Warnung einen Absatz zu spät. Ich finde, gerade wegen der Häufigkeit des Antreffens, sollte man das direkt als erstes unter den Code-Kasten schreiben. Oder als Kommentar über die Schleife?

Code: Alles auswählen

# Bitte so nicht machen, denn das ist ein typischer Anfängerfehler. Wieso steht weiter unten
Und die Erklärung noch um die Übeltäter ergänzen:
Leider ist obiger Code schlecht! Er ist eines der berühmten Anti-Pattern, die man häufig bei Anfängern oder Umsteigern von anderen Sprachen sieht. Durch den Aufruf zweier, in diesem Zusammenhang, unnötiger Funktionen (range() und len()) wirkt der Code unleserlicher, ausserdem ist er unnötig kompliziert.
So kann man auch als Laie das Anti-Pattern erkennen, da es nun konkret benannt ist durch Nennung von `range()` und `len()`.

Frank
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe Deine Ideen zum Teil übernommen. Die Warnung im Code mag ich nicht einführen, da der Leser zum einen sonst frühzeitig abgelenkt wird und zum anderen demotiviert wird, das ganze zu durchdenken. Er soll ja genau darauf hingeführt werden, wie viel einfacher und leserlicher die Lösung mittels `enumerate` ist. Genauso so habe ich es ja auch mit der "schlechten" Lösung des Gesamtproblems gehandhabt: Erst einmal vorstellen und dann erklären, wieso man das nicht so machen sollte und die sinnvolle Lösung aufzeigen. Ich denke, dass ich so der Stil des Tutorials und den mag ich nicht brechen. Wer die Warnung dann überliest, der wird das Tutorial eh nicht richtig durcharbeiten und somit nichts lernen :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Ja, so kann man es machen, da stimme ich dir zu. Gerade der Teil mit der Konsistenz kann imo nicht überbewertet werden. Man könnte solche Hinweise natürlich noch etwas stärker hervorheben. Keine Ahnung, ob Markdown da etwas anbietet. Inspiriert haben mich da ein paar Lehrbücher, da gibt es ja auch öfter mal so Kästchen und Zeigefinger-Grafiken.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ja, solche Hervorhebungen wären schon nett. Genauso stört es mich, dass das Syntaxhighlighting für die Konsolensessions nicht gut funzt.

Also an alle Github-Erfahrenen: Gibt es da ein spezielles Highlighting? Und gibt es solche Hervorhebungen?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Hyperion hat geschrieben:Genauso stört es mich, dass das Syntaxhighlighting für die Konsolensessions nicht gut funzt.
Dafür gibt es das „pycon“-Syntax-Highlighting, das aber nur für „normale“ Python-Sitzungen funktioniert.
Hyperion hat geschrieben:Und gibt es solche Hervorhebungen?
***Das ist die stärkste Hervorhebung.*** ;)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

nomnom hat geschrieben:Dafür gibt es das „pycon“-Syntax-Highlighting, das aber nur für „normale“ Python-Sitzungen funktioniert.
Also nicht für IPython? Ich werds mal testen, vielleicht ist das ja doch akzeptabel :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich würde IPython eh weglassen. Das verwirrt mehr als es wert ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Tolles Tutorial. Guter Schreibstil. Da muss ich im Vergleich mein Tutorial noch zurückhalten und überarbeiten :)

Ich schlage ebenfalls vor, auf IPython zu verzichten. Das verwirrt mehr, als es hilft, auch wenn es praktisch scheint, um auf Ausdrücke zu verweisen. Zudem finde ich's doof, dass Pygments das "ü" und "ö" als Fehler hervorhebt oder andere komische Dinge mit der Ausgabe macht.

Ich würde auch auf "sys.exit()" verzichten und einfach "break" benutzen. Das macht in den ersten Beispielen die Funktion "menu" wiederverwendbar.

Wenn du format() nicht zum Formatieren benutzt, würde statt

Code: Alles auswählen

    print("{}  {}".format(index+1, menu[index]))
auch einfach

Code: Alles auswählen

    print(index+1, menu[index])
funktionieren. Und da ich eher ein Fan von "%" bin, würde ich wenn schon, dann

Code: Alles auswählen

    print("%2d .. %s" % (index + 1, menu[index]))
benutzen, damit auch Zahlen > 9 noch schön untereinander ausgerichtet werden.

Übrigens, man darf in einem Tutorial ruhig lügen, wenn es dem Verständnis dient. Die Aussage "alles ist ein Objekt" kann man IMHO so stehen lassen. Ich würde wahrscheinlich von Werten sprechen, nicht Objekten, um sie klar von Exemplaren abzugrenzen. Letztlich ist aber in Python AFAIK auch alles ein Exemplar einer Klasse, selbst Klassen. Etwas wie "ich kann jeden Wert in ein dict stecken" würde dann aber auch gehen. Der Exkurs "Funktionen sind auch Objekte" ist IMHO ein bisschen zu lang. Ehrlich gesagt würde ich Objekte komplett raus lassen und nur argumentieren, dass Funktionen Werte sind, und damit überall dort benutzt werden können, wo man andere Werte wie Zahlen oder Zeichenketten benutzen kann (sie sind "first class").

Bei

Code: Alles auswählen

    x >= 0 /\ x < 10
kannst du übrigens die Macht von Unicode spielen lassen :)

Code: Alles auswählen

    x ≥ 0 ∧ x < 10
Als Tipp, wie es weitergehen könnte: Annotiere Funktionen mit `@menu(x)`, um sie auf diese Weise in ein Menü `x` einzufügen. Sie werden in der Reihenfolge eingefügt, wie sie im Quelltext stehen. Der letzte Punkt ist immer "Ende" bzw. "Zurück", wenn es sich um ein Untermenü handelt.

Stefan
BlackJack

@sma: Ich mag ``%`` ja auch lieber, aber Zahlen auf x Stellen zu formatieren geht auch mit `format()`:

Code: Alles auswählen

In [206]: '{0:2d}'.format(1)
Out[206]: ' 1'
sh4nks
User
Beiträge: 13
Registriert: Montag 5. März 2012, 22:08
Wohnort: Styria

Danke für dieses Tutorial :)

Ich hätte noch eine kleine Frage beim submenu

Was macht das underline?

Konnte bei Google nichts finden, da ich nicht weiß was die genaue Bezeichnung ist
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

sh4nks hat geschrieben:Was macht das underline?

Konnte bei Google nichts finden, da ich nicht weiß was die genaue Bezeichnung ist
Der under_score_ hat in Python keine besondere Bedeutung, sondern ist ein ein ganz normaler Bezeichner.
Fuer Programmierer hat er aber meistens zu bedeuten "Ich bekomme Werte, die ich nicht nutze, und will das kenntlich machen".
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

sh4nks hat geschrieben:Was macht das underline
Das ist ein ganz normaler gültiger Name für einen Bezeichner. Der Code hätte statt

Code: Alles auswählen

_, command = menu
auch

Code: Alles auswählen

name, command = menu
aussehen können, vor allem da der erste Parameter im folgenden Code nicht mehr verwendet wird.

Und das ist genau der Knackpunkt an der Sache. Eine nicht unerhebliche Anzahl von Python-Entwicklern verwenden den Unterstrich als Bezeichner an Stellen wo ein Bezeichner gebraucht wird, der anschließend keine Rolle mehr spielt. Der Unterstrich ist absolut nichtssagend und genau das ist es, was die Bedeutung dieses Parameters dort im Code ausmacht.

Ab und zu wird der Unterstrich von manchen Entwicklern auch als Verkürzung für oft verwendete Funktionen benutzt.

Code: Alles auswählen

>>> from __future__ import print_function
>>> _ = print
>>> _('Hallo')
Hallo
Ich mag diesen Einsatz nicht so. Er konterkariert PEP-20 (Zen of Python) und PEP-8 bei den Punkten "Readability counts." unter besonderer Berücksichtigung von "code is read much more often than it is written".
sh4nks
User
Beiträge: 13
Registriert: Montag 5. März 2012, 22:08
Wohnort: Styria

Ah ok danke.

Dies würde aber so auch funktionieren:

Code: Alles auswählen

command = menu[choice][1]
Ist es eine schlechte Idee das so zu verwenden?
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das würde auch funktionieren, nur macht es mMn. unleserlicher.
the more they change the more they stay the same
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

/me hat geschrieben:Ich mag diesen Einsatz [gemeint ist der Unterstrich] ]nicht so. Er konterkariert PEP-20 (Zen of Python) und PEP-8 bei den Punkten "Readability counts." unter besonderer Berücksichtigung von "code is read much more often than it is written"
Ich finde den "_" im Gegenteil "intention revealing" und auch wenn Python das im Gegensatz zu anderen Sprachen nicht als Teil der Semantik kennt, ist es IMHO guter Stil. Ein anderes Beispiel wäre "i" für eine Schleifenvariable oder das man eine Pluralform wählt, wenn man eine Collection von Dingen bezeichnen will.

Die Python-IDE PyCharm weiß bei ihrer heuristischen Typanalyse beispielsweise, dass sie das "_" nicht an unbenutzt Variable markieren soll. Würde man `foo, bar = foobars` schreiben und dann `foo` nie wieder benutzen, würde PyCharm das als wahrscheinlichen anmerken.

Stefan
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

sma hat geschrieben:Ich finde den "_" im Gegenteil "intention revealing" und auch wenn Python das im Gegensatz zu anderen Sprachen nicht als Teil der Semantik kennt, ist es IMHO guter Stil. Ein anderes Beispiel wäre "i" für eine Schleifenvariable oder das man eine Pluralform wählt, wenn man eine Collection von Dingen bezeichnen will.
Hier scheine ich den Kontext nicht deutlich genug gemacht zu haben. Ich mag den Unterstrich "als Verkürzung für oft verwendete Funktionen" nicht, sonst durchaus.
sma hat geschrieben:Die Python-IDE PyCharm ...
Gerade habe ich noch 66,70€ für das Upgrade Subscription Renewal ausgegeben. Und das mir als FSFE-Fellow ...
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

/me hat geschrieben:Hier scheine ich den Kontext nicht deutlich genug gemacht zu haben. Ich mag den Unterstrich "als Verkürzung für oft verwendete Funktionen" nicht, sonst durchaus.
Ach so. Ja, das teile ich.
sma hat geschrieben:Die Python-IDE PyCharm ...
/me hat geschrieben:Gerade habe ich noch 66,70€ für das Upgrade Subscription Renewal ausgegeben. Und das mir als FSFE-Fellow ...
Wird nicht immer gepredigt: Free != Kostenlos ;) Gute Software darf ruhig etwas kosten, finde ich.

Außerdem: Die Grund-IDE von Jetbrains für Java, Scala und Android ist ja außerdem auch als Opensource verfügbar...

Stefan
Antworten