Code-Review zur Thematik "Konstanten"

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

Hallo zusammen,

ich bin ein wenig ratlos, ob eine Konstante im folgenden Code wirklich eine gute Idee ist:
Ziel ist, möglichst gut lesbaren, wartbaren Code zu produzieren.

Code: Alles auswählen

FIRST_LETTER = 0


def is_capitalized(word):
    return word[FIRST_LETTER] == word[FIRST_LETTER].upper()


def main():
    print(is_capitalized("Hallo"))
    print(is_capitalized("ween"))


if __name__ == '__main__':
    main()
Ich habe auch hierzu schon die Beiträge aus 2007 konsultiert: viewtopic.php?t=8338
Eine eigene Klasse für die Konstanten, erscheint mir im konkreten Fall etwas "to much".
Was meint ihr?

Findet ihr den obigen Code gut lesbar?
Mir erscheint, sowas wie "word[0]" nicht ideal lesbar. Wie seht ihr das?
Ist eine Konstante hier eine gute Idee? Oder wäre eine lokale Variable (?) wie hier besser?

Code: Alles auswählen

def is_capitalized(word):
    first_letter = 0
    return word[first_letter] == word[first_letter].upper()


def main():
    print(is_capitalized("Hallo"))
    print(is_capitalized("ween"))


if __name__ == '__main__':
    main()
Ich bin mir unsicher wg. der "Globalität" der Konstante. (In Delphi hätte ich hier vermutlich eine lokale Konstante eingefügt. Sprich den Scope auf die Funktion begrenzt. Aber in Python scheint das unüblich zu sein. Irre ich mich?)


Ich danke Euch für Euer Feedback zu meinen Fragen

LG
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

An sich finde ich das Gezeigte vom Prinzip her richtig. Im konkreten Fall würde ich aber einfach 'word[0]' schreiben, da das eigentlich doch schon gut verständlich und das erste Element einer Sequenz in Python auch nicht verhandelbar ist. Es ist also weder ein arbiträrer "magischer Wert" wie 23, noch etwas, das man später umändern möchte. Ich sehe keinen wirklichen Mehrwert darin, statt 0 nun "FIRST_LETTER" zu schreiben. Diskutieren könnte man jetzt noch über den Fall von Sprachen, die von Rechts nach Links geschrieben werden. Aber hier ist ja die Frage, ob die interne Repräsentation der präsentierten entsprechen muss.

Wenn es sich um mehrere aufeinander bezogene Werte handelt, gibt es in Python auch Enums in der Standardbibliothek. Aber auch die bieten sich hier eigentlich nicht an.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Ich würde auch eher word[0] verwenden. word[FIRST_LETTER] ist recht aussagekräftig, aber eben nicht so klar wie der direkte weg.
Bei so etwas ist eine Konstante meiner Meinung nach erst hilfreich wenn sie an mehrere Stellen im Code verwendet wird, und man sich die Flexibilität, wünscht den Wert an mehreren Stellen gleichzeitig zu ändern.
Im konkreten Fall besteht kein Bedarf der Wert der Konstante je zu ändern.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@nezzcarth und @rogerb

vielen lieben Dank für Eure Einschätzung.

In meiner ersten Version hatte ich tatsächlich word[0] geschrieben, bin jedoch dann wieder davon abgekommen. Im Grunde wäre damit die Lesbarkeit aber durch den Funktionsnamen* bereits gegeben.

*) ich bin gar nicht sicher, ob das in Pyhton die richtige Vokabel ist...
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

Übrigens: Strings haben in Python eine eingebaute Methode 'istitle()', die etwas ganz ähnliches macht und die du ggf. stattdessen verwenden könntest.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@nezzcarth

Danke, vielmals. Ja, das ist eine gute Idee! :)
Benutzeravatar
__blackjack__
User
Beiträge: 14020
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich wäre da vorsichtig, denn es gibt. `str.capitalize()`, `str.title()`, und `str.istitle()`. Eine Methode `iscapitalize()` gibt es nicht, und `istitle()` ist das Gegenstück zu `title()`. Wenn man also wirklich einen Test braucht der das Gegenstück zur `capitalize()`-Methode ist, geht `istitle()` nicht generell und man muss sich da tatsächlich selbst was schreiben. Streng genommen reicht da auch nicht nur das testen des ersten Zeichens. Und man muss auch überlegen was man bei einer leeren Zeichenkette macht. Ich würde mich da an `istitle()` orientieren, damit das einheitlich ist.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@__blackjack__
dankeschön :)

Ich bin mir nicht ganz sicher, ob ich Dich richtig verstanden habe.

Das Verhalten von istitle(), passt zu meinem UseCase. Ich möchte Wörter "herausfinden", die groß geschrieben sind. (Genau genommen, will ich Nomen - aber ich fürchte, dass das kein ganz triviales Vorhaben ist.)

Code: Alles auswählen

print("Test".istitle())
print("test".istitle())
print("tEst".istitle())
print("TEst".istitle())
print("TEST".istitle())
print("".istitle())

Zwischenzeitlich ist mir noch folgende Frage gekommen:

Ich lese ganz oft in Beiträgen, dass def main() ganz unten steht:
z.B. hier viewtopic.php?f=1&t=53252&p=395505&hili ... in#p395505

Ist das in Python so üblich/korrekt?
Ich frage, weil ich das hier jetzt mehr oder weniger unbewusst so übernommen habe, allerdings würde ich das normalerweise nicht so tun, wie mir bei einigem Nachdenken aufgefallen ist. Da würde ich eher "von oben nach unten" schreiben - also main() ganz oben und darunter der Rest.

LG
Benutzeravatar
kbr
User
Beiträge: 1506
Registriert: Mittwoch 15. Oktober 2008, 09:27

"main" ist nur der Entry-Point, der keineswegs so heißen muß und auch irgendwo stehen darf. Ich halte es aber auch gerne so, diesen "main" zu nennen und unten im Code über der __name__ Weiche anzusiedeln.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@kbr
lieben Dank für die Info.

Gibt's eigentlich einen speziellen Grund, warum das in Python immer(?)/oft unten steht?
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

Um Wortarten zuverlässig zu bestimmen, setzt man einen Part-of-Speech Tagger (POS-Tagger) für die jeweilige Sprache ein. Die großen NLP Pakete für Python bringen so etwas oft schon mit.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dinge müssen ja erst definiert werden, bevor sie benutzt werden. Wenn du also das ganze an den Anfang stellst, und in deiner main Funktion eine andere in der Datei definierte benutzt, war der Interpreter da ja noch gar nicht dran vorbei gekommen. Zumindest der eigentliche __main__-Guard muss also am Ende kommen. Main könnte auch irgendwo darüber definiert werden, aber ich sortiere generell gerne von “wird von anderen Funktionen benutzt” nach oben. Das ist eine Angewohnheit aus Sprachen wie C, die sonst einen Prototypen brauchen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

nezzcarth hat geschrieben: Sonntag 31. Oktober 2021, 17:18 Um Wortarten zuverlässig zu bestimmen, setzt man einen Part-of-Speech Tagger (POS-Tagger) für die jeweilige Sprache ein. Die großen NLP Pakete für Python bringen so etwas oft schon mit.
Falsches Forum? Ich habe neulich mal das Gefühl gehabt, das mir das auch passiert ist, und ein bug war 😕
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

@__deets__: Ich hatte Buchfink so verstanden, dass die Großschreibung als Heuristik herangezogen werden soll, um Nomina zu bestimmen; darauf bezog sich mein Hinweis. Wenn ich das falsch verstanden habe, ziehe ich das natürlich zurück.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@nezzcarth: nee, das war dann ich. Es gab gerade noch ein anderes Sprachverstehen-Thema, und hier driftete die Diskussion zu anderen Dingen. Darum mein Eindruck.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@nezzcarth
dankschön für den Hinweis :)
In diese Richtung habe ich auch schon gedacht.

Es geht allerdings ja nur um ein Spaßprojekt (hier im ersten Beitrag beschrieben viewtopic.php?f=30&t=53265)

Im Moment habe ich noch sehr viele Fragen .. Ich "zerlege" das daher in kleinere Teilaspekte, weil ich sonst ständig die Threads kreuze und das ist vermutlich nicht so ideal.
Also ich kriege alles hin, aber ich lerne halt über die Fragen, die ich hier stellen kann - sprich über die Interaktion. Ich lerne auch aus anderen Beiträgen, da ich diese oft still mitlese und versuche das dort gesehene selbst anzuwenden.
Vielen Dank nochmals für Eure Geduld mit mir!

Wenn ihr mögt, kann ich auch gerne mal den Zwischenstand des gesamten Codes (den ich bisher habe) hier posten - dann könnt ihr gerne mal sagen, ob das was taugt. Allerdings muss ich dazu sagen, dass ich an vielen Stellen selbst noch sehr unzufrieden bin.
Und ich möchte nicht Eure Zeit stehlen.... daher bin ich etwas vorsichtig, denn es ist nicht ideal reproduzierbar, da man z.B. eine Datei einlesen muss (ich habe allerdings schon Ideen, wie ich das verbessern könnte)

Soll/darf ich trotzdem mal alles posten?

LG
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@nezzcarth
Ich hatte Buchfink so verstanden, dass die Großschreibung als Heuristik herangezogen werden soll, um Nomina zu bestimmen; darauf bezog sich mein Hinweis. Wenn ich das falsch verstanden habe, ziehe ich das natürlich zurück.
Du hast mich richtig verstanden.
Ich möchte Nomen aus Texten extrahieren, um diese durch Reimwörter zu ersetzen.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@__deets__
Dinge müssen ja erst definiert werden, bevor sie benutzt werden. Wenn du also das ganze an den Anfang stellst, und in deiner main Funktion eine andere in der Datei definierte benutzt, war der Interpreter da ja noch gar nicht dran vorbei gekommen. Zumindest der eigentliche __main__-Guard muss also am Ende kommen.
lieben Dank für die Erklärung. Jetzt verstehe ich das.
Benutzeravatar
kbr
User
Beiträge: 1506
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Buchfink: Es ist so ein wenig "C-Heritage" das ich gerne Funktionen (bzw. allgemein "callables") vor ihrem Aufruf im Code anlege. Dem Python-Compiler ist das aber egal und erst zur Runtime wird es wichtig, ob ein callable bereits bekannt ist. Du machst mit C-Gewohnheiten in Python jedoch nichts falsch, auch wenn Python sich hier ein wenig anders verhält. Nur, wie __deets__ schon schrieb, ist es wichtig, dass die __main__-Weiche am Schluß kommt, und dort idealerweise nur ein Funktionsaufruf erfolgt.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@kbr

verstehe. Ich habe mich bereits auch an diese "Lese-/Schreibrichtung" gewöhnt, muss ich sagen. (Glaube ich jedenfalls)
Ich hatte vorhin jedoch zufällig (ehrlich:)) das Buch "Clean Code" in der Hand und bisschen drin geblättert, weil ich was anderes gesucht hatte. Nun ja, so kam ich drauf :)
Dort wird vorgeschlagen Funktionen "von oben nach unten" zu schreiben.
Mir fiel dann auf, dass sich das "unpythonisch" anfühlt. Aber ich konnte es nicht begründen...
Ich vermute, durch das stille Mitlesen entwickelt man vielleicht trotzdem auch ein "Gefühl" dafür, was üblich ist und was eher nicht.

Lieben Dank jedenfalls für Eure Erklärungen
Antworten