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

@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
Benutzeravatar
kbr
User
Beiträge: 1506
Registriert: Mittwoch 15. Oktober 2008, 09:27

Ja, "Uncle Bob" hat seine Marktlücke gefunden – mit dem diskutiert man daher wohl besser nicht ;)
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

Jede Sprache hat wohl ihre individuellen Eigenschaften, die man eben verstehen muss. :)
Benutzeravatar
__blackjack__
User
Beiträge: 14028
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Buchfink: Für *den* Einsatzzweck ist es egal ob Du `istitle()` oder ein Gegenstück zu `capitalize()` verwendest, denn es geht nur um ein Wort. Da unterscheiden sich `title()` und `capitalize()` nicht. Bei mehr als einem Wort macht es aber einen Unterschied:

Code: Alles auswählen

In [380]: "foo bar".title()                                                     
Out[380]: 'Foo Bar'

In [381]: "foo bar".capitalize()                                                
Out[381]: 'Foo bar'
`main()` definiere ich, wie wohl die allermeisten anderen auch, als letztes, nicht nur aus Gewohnheit beispielsweise aus C oder Pascal, sondern auch aus Konsistenzgründen.

Man kann ja auch der Meinung sein, dass man erst das ”grosse, grobe Bild malt” und die kleineren detaillierteren Teile danach ausfüllt. Also von der Hauptfunktion startend, und dann die Einzelschritte, bis zu Detailaufgaben und Hilfsfunktionen runter, der Quelltext im Laufe der Datei immer spezieller wird. Das Problem bei Python ist, dass man das nicht sauber durchhalten kann, weil das nicht in statische Programmanalyse zuerst und dynamische Laufzeit danach aufgeteilt ist, sondern auch der Modulinhalt ausführbarer Code ist, und alles was man verwendet, vorher definiert sein muss. Und zumindest alles was man für das ausführen von ``class``- und ``def``-Anweisungen benötigt, muss vorher definiert worden sein, auch wenn es kleinere Details sind.

Das betrifft beispielsweise Dekoratoren und alles was man so für Defaultargumente braucht. Also beispielsweise auch Funktionen oder Klassen.

Und dann gibt es auch noch Fälle wo Funktionen nicht per ``def`` definiert werden, sondern aus anderen Funktionen erstellt werden, die dafür vorher aber definiert worden sein müssen, auch wenn das nur Hilfsfunktionen sind, die nicht einmal zur öffentlichen API gehören.

Also beispielsweise würde man ja für eine Cäsar-Chiffre `encode()` und `decode()` vor einer Hilfsfunktion definieren, wenn man vom groben, zum Detail gehen würde. Das kann man machen, wenn man `encode()` und `decode()` tatsächlich als Funktionen hin schreiben will, aber nicht wenn man die beiden Funktionen aus der Hilfsfunktion + Parameter erstellt.

Also das hier geht:

Code: Alles auswählen

def encode(text, key):
    return _code(add, text, key)


def decode(text, key):
    return _code(sub, text, key)


def _code(offset_function, text, key):
    ...
Aber das hier ginge nicht:

Code: Alles auswählen

encode = partial(_code, add)
decode = partial(_code, sub)

def _code(offset_function, text, key):
    ...
Da müsste man dann anfangen gegen die selbst gesteckten Reihenfolgeregeln zu verstossen, oder man schränkt sich freiwillig ein, bestimmte Spracheigenschaften und Möglichkeiten nicht zu nutzen.
„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__
Bei mehr als einem Wort macht es aber einen Unterschied:
verstehe :) lieben Dank und gut zu wissen, denn dann wäre mein vorheriger Funktionsname ohnehin auch noch semantisch falsch/verwirrend gewesen.
Man kann ja auch der Meinung sein, dass man erst das ”grosse, grobe Bild malt” und die kleineren detaillierteren Teile danach ausfüllt. Also von der Hauptfunktion startend, und dann die Einzelschritte, bis zu Detailaufgaben und Hilfsfunktionen runter, der Quelltext im Laufe der Datei immer spezieller wird.
ja genau, das schlägt Hr. Martin vor.

hier mal der gesamte Code, wie ich ihn nun habe:

Auszug Sprueche.txt

Code: Alles auswählen

A
"Abends werden die Faulen fleissig." - Citatboken, Bokförlaget Natur och Kultur, Stockholm, 1967, ISBN 91-27-01681-1
"Abwarten und Tee trinken." - Wander-DSL, Bd. 5, Sp. 702, commons. (Dort zitiert als: "Abwarten und Theetrinken.")
"Adel verpflichtet." (Noblesse oblige) - nach Pierre-Marc-Gaston de Lévis, Maximes et réflections
"Alle Menschen in der Welt streben nur nach Gut und Geld; und wenn sie es dann erwerben legen sie sich hin und sterben." - Citatboken, Bokförlaget Natur och Kultur, Stockholm, 1967, ISBN 91-27-01681-1
"Alle Sünden in eine münden."
"Alle Wege führen nach Rom." - Wander-DSL, Bd. 4, Sp. 1842, commons
"Aller Anfang ist schwer." - Wander-DSL, Bd. 1, Sp. 80, commons
"Aller guten Dinge sind drei." - Wander-DSL, Bd. 1, Sp. 605, commons. (Dort zitiert als: "Aller guten Ding seynd drey.")
"Alles Gute kommt von oben."
"Alles hat seine Zeit, nur die alten Weiber nicht." - Wander-DSL, Bd. 1, Sp. 46, commons
"Alles neu macht der Mai." - nach dem Gedicht von Hermann Adam von Kamp "Alles neu, macht der Mai" (1818)

Code: Alles auswählen

from pathlib import Path


def investigate_sayings():
    # TODO
    # Verbesserung mittels wiki-api - Texte direkt aus Wikipedia "Sprichwörter" auslesen?
    # Methode "tut" zu viel - Zerlegen in Beschaffung der Daten und Erstellen des Datenmodells
    filename = Path("C:/Users/Buchfink/Documents/Projkete/WortspielGenerator/Sprueche.txt")
    with open(filename, "r", encoding="UTF-8") as file:
        investigated_sayings = {}
        for line in file:
            splitted = line.strip().split(".\"")

            saying = splitted[0].strip().replace('\"', '')
            if len(saying) == 1:
                continue

            words = saying.split(" ")
            interesting_words = []
            for word in words:
                if word.istitle():
                    interesting_words.append(word)
            investigated_sayings[saying] = interesting_words
    return investigated_sayings


def get_rhyme(word):
    # TODO
    # Quelle ist noch unklar. Daher nur mal exemplarische simplifizierte Beispielzuordnung
    # Ungelöste Probleme:
    #  - Quelle selbst, hardcodiert ist ja keine Lösung :)
    #  - Artikelproblem - gleicher Artikel funktioniert immer, unterschiedliche Artikel eher weniger (kontextabhängig)
    #  - es gibt ggf. mehrere Reimwörter pro Wort,
    #  - Plural vs. Singular
    #  - Beidseitigkeit - sprich Laus reimt sich auf Maus und umgekehrt. Man könnte vereinfachen, indem man
    #    jedes Pärchen nur einmal einfügt
    rhymes = {
        "Esel": "Sessel", "Sessel": "Esel",
        "Geld": "Held", "Held": "Geld",
        "Spiegel": "Igel",  "Igel": "Spiegel",
        "Kopf": "Topf", "Topf": "Kopf",
        "Baum": "Raum", "Raum": "Baum",
        "Berg": "Zwerg", "Zwerg": "Berg",
        "Laus": "Maus", "Maus": "Laus",
        "Adel": "Sargnagel", "Sargnagel": "Adel",
        "Wunsch": "Punsch", "Punsch": "Wunsch",
        "Flügel": "Kleiderbügel",
        "Waffen": "Karaffen",
        "Macht": "Verdacht"
    }
    rhyme = rhymes.get(word)
    return rhyme


def substitute_with_rhymes(investigated_sayings):
    substituted_sayings = []
    for key, value in investigated_sayings.items():
        for word in value:
            substituted_word = get_rhyme(word)
            if substituted_word is not None:
                substituted_sayings.append(key.replace(word, substituted_word))
    return substituted_sayings


def show_sayings(sayings):
    for saying in sayings:
        print(saying)
    print(f"Anzahl {len(sayings)}")


def main():
    investigated = investigate_sayings()
    substituted = substitute_with_rhymes(investigated)
    show_sayings(substituted)


if __name__ == '__main__':
    main()
Ich denke, dass das wohl eine pythonische Reihenfolge ist - korrekt?

Am Rande:
Der Code tut was er soll. Aber Ich bin trotzdem ein bisschen unglücklich damit. Hier mal eine Liste all meiner Unglücksfaktoren

1) Ich lese aus einer Datei. Für ein Code-Review ist das blöd, denn man kann den Code dann nicht einfach mal ausprobieren. Ich möchte hier wenn's geht, keine riesigen Aufwände generieren. Dieser Code in investigate_sayings() ist daher schlecht.
Verbesserungsvorschlag: direkt aus Wikipedia auslesen. Ich bin hier aber noch am Recherchieren wie das genau geht und melde mich ggfls. mit konkreten Fragen

2) Das Datenmodell gefällt mir nicht. Es fühlt sich falsch an, einen Spruch als "key" zu missbrauchen. Ein Key mit Leerzeichen oder Umlauten ist irgendwie schräg.
Verbesserungsvorschlag: Klassen, die die Daten halten.
Was meint ihr so?

3) hardcodierte Reim-Zuordnung. Tja nun :) Es ist nur ein Prototyp und ich wollte erst mal sehen, ob das überhaupt eine gute Idee ist. Letztlich musss da aber was generisches hin.

4) Algorithmus zur Substitution: hier könnte man auch flexibler werden und vielleicht mal gucken wollen, ob man statt Reime Synonyme oder Antonyme durchprobiert. :)
Hier mangelt es an Flexibilität aus meiner Sicht.
Verbesserungsvorschlag: auf ein Klassenmodell umziehen und dann mittels Polymorphie (oder Funktion als Parameter?)

5) Algorithmus zum Finden interessanter Wörter: könnte man auch für Verben haben wollen. Nomen sind halt leichter heuristisch einigermaßen erkennbar, daher sind es im ersten Wurf Nomen geworden.

6) Main: könnte man auch mit einem Einzeiler schreiben.
Zum debuggen finde ich es manchmal praktischer, wenn es nicht ganz so kompakt steht. Was meint ihr denn?

7) siehe TODOs im Code selbst.

8) continue.... tja nun... ich bin unentschlossen. Ich mag "continue" eigentlich gar nicht. Besser in zwei Funktionen splitten? Ein If erhöht halt wiederum die Verschachtelungstiefe. Was meint Ihr?

Es gibt noch einen Haufen Aspekte, die man verbessern könnte. Ich poste den Code hier mal, damit Ihr einen Eindruck bekommt, was ich so mache.

Ich freue mich auf Euer Feedback! :)

LG
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Buchfink,

also dem meisten, was du selbst schon angemerkt hast, würde ich zustimmen.
Unter Punkt 2 würde ich aber nicht auf eine Klasse als Datenbehälter wechseln, solange ein Dictionary ausreicht. man kann ja auch die Struktur anpassen:

Code: Alles auswählen

investigated_sayings = [
    {
        "originalsentence": "...",
        "keywords": [...]
    },
    ...
]
Beim iterieren über dict.items() würde ich nicht "key", "value" sondern aussagekräftige Namen verwenden.
Wenn eine Variable eine Datensequenz enthält würde ich den Plural verwenden:

Code: Alles auswählen

for word in keywords:
"is not None" kann man ersetzen:

Code: Alles auswählen

if substituted_word is not None:

Code: Alles auswählen

if substituted_word:
So etwas schreit nach einer List-Comprehension, Dict-Comprehension, oder Generator-Expression.

Code: Alles auswählen

interesting_words = []
for word in words:
    if word.istitle():
        interesting_words.append(word)
Aber die Funktion investigate_sayings() muss ja sowieso aufgeteilt werden, da kann man die Teile dann vielleicht schon als Generator anlegen.
Zuletzt geändert von rogerb am Montag 1. November 2021, 11:57, insgesamt 1-mal geändert.
nezzcarth
User
Beiträge: 1753
Registriert: Samstag 16. April 2011, 12:47

Zu deinen Punkten 3 und 4: Statt mit harded-coded Zuordnungen zu arbeiten, könntest du natürlich auch Wörterbücher in Dateiform hinterlegen. Aus meiner Sicht ist das für ein Hobby-Projekt um Python zu lernen vermutlich der Ansatz, mit dem du am schnellsten schöne Ergebnisse erhalten wirst. Was auch ganz gut und relativ einfach klappen könnte, ist statt "Voll-Reimen" Assonanzen und/oder Alliterationen/Stabreime zu nehmen. Oder man versucht es ggf. mit anderen heuristischen Ansätzen wie Ähnlichkeitsmaßen (Kölner Phonetik; (gewichtete) Levenshteindistanz, etc.). Wenn man das Erkennen von Endreimen automatisieren und das Problem "NLP-mäßig" angehen will, ist das nämlich nicht trivial und erfordert (denke ich) die Auseinandersetzung mit entsprechenden Algorithmen (z. B. zur Silbentrennung).
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@rogerb und @nezzcarth

ganz lieben Dank für Euren Input.
Unter Punkt 2 würde ich aber nicht auf eine Klasse als Datenbehälter wechseln, solange ein Dictionary ausreicht
ja - genau sowas hab ich gesucht. Ich wusste nicht (wie/dass) das geht. Danke für den Hinweis!
Unter Delphi hätte ich vielleicht eine Klasse gebaut, die eine Generics-Liste aggregiert. Aber das fühlte sich _hier_ auch nicht richtig an, weil zu schwergewichtig. (Manchmal fühlen sich Dinge irgendwie nicht "pythonisch" an... )
"is not None" kann man ersetzen:
--> das hab ich direkt korrigiert.
List-Comprehension, Dict-Comprehension, oder Generator-Expression.
Das werde ich erst googeln müssen, bevor ich konkrete Fragen dazu stellen kann.

Es ist immer wieder erstaunlich, welche Detailfülle sich da manchmal ergibt. :) Aber es macht Spaß von Euch was zu lernen.
Wenn man das Erkennen von Endreimen automatisieren und das Problem "NLP-mäßig" angehen will, ist das nämlich nicht trivial und erfordert (denke ich) die Auseinandersetzung mit entsprechenden Algorithmen (z. B. zur Silbentrennung).
Es ist schwer zu sagen, wo das irgendwann hingeht. Ich finde Sprache als solches tatsächlich ziemlich interessant. (Mein Name ist eine Anspielung auf den Umstand, dass ich andauernd irgendein Buch lese).
Ob ich allerdings intellektuell in der Lage bin, solche Algorithmen dann tatsächlich zu verstehen, steht auf einem anderen Blatt. :)
Ich bin da selbst gespannt wie ein Regenschirm :)

LG
narpfel
User
Beiträge: 690
Registriert: Freitag 20. Oktober 2017, 16:10

@Buchfink: Ich würde an der Stelle keine Liste von Dicts mit implizit festgelegter Struktur benutzen, sondern eher ein `collections.namedtuple` oder auch ein `collections.defaultdict(list)`:

Code: Alles auswählen

In [1]: from collections import namedtuple, defaultdict

In [2]: Saying = namedtuple("Saying", "sentence, keywords")

In [4]: Saying("foo", ["bar"])
Out[4]: Saying(sentence='foo', keywords=['bar'])

# oder

In [5]: sayings = defaultdict(list)

In [6]: sayings["foo"].append("bar")

In [7]: sayings["foo"].append("baz")

In [9]: sayings["spam"].append("eggs")

In [10]: sayings
Out[10]: defaultdict(list, {'foo': ['bar', 'baz'], 'spam': ['eggs']})
Wobei ich eher zum `defaultdict` tendieren würde, weil man darin direkt die Zuordnung eingebaut hat und nicht linear suchen muss, wenn man auf ein bestimmtes Sprichwort zugreifen will. Ein Dict mit beliebigen Strings als Keys ist IMHO nicht komisch.

Ich schreibe zwar auch gerne `if xs` oder `if not xs`, um auf eine leere Collection zu testen, aber `if foo` statt `if foo is not None` schreibe ich nie, weil das auch bei „leeren“ (bzw. allgemein „falsy“) Werten ins `if` springt. „Explicit is better than implicit.“
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@narpfel,
aber `if foo` statt `if foo is not None` schreibe ich nie, weil das auch bei „leeren“ (bzw. allgemein „falsy“) Werten ins `if` springt.
Nicht sicher was du genau mit "leeren Werten" meinst, bei keinem dieser falsy Werte würde der if-Zweig ausgeführt.

Code: Alles auswählen

falsy_values = [list(), dict(), tuple(), range(0), 0.0, 0, False, set(), None, ""]

for thing in falsy_values:
    if thing:
        print(f"{thing} is truthy")
    else:
        print(f"{thing} is falsy")

"""
[] is falsy
{} is falsy
() is falsy
range(0, 0) is falsy
0.0 is falsy
0 is falsy
False is falsy
set() is falsy
None is falsy
 is falsy
"""
Benutzeravatar
__blackjack__
User
Beiträge: 14028
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@rogerb: Genau das war gemeint: das trifft auf viele Werte zu, nicht nur auf `None`. Und vielleicht möchte man das nicht. Oft denkt man an solche Randfälle ja auch nicht. Oder denkt sich, der Fall kann ja eh nicht vorkommen. Und dann ist man stundenlang mit Fehlersuche beschäftigt. :-)
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
narpfel
User
Beiträge: 690
Registriert: Freitag 20. Oktober 2017, 16:10

@rogerb: Flüchtigkeitsfehler, muss natürlich „nicht ins `if` springt“ heißen. Der Punkt ist, dass mit `if foo` nicht zwischen `None` und allgemein falsy unterscheiden werden kann, deswegen besser `if foo is not None`.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@narpfel

dankeschön für die Links und die Tipps

ich vermute, Du meinst _so_?

Code: Alles auswählen

from pathlib import Path
from collections import defaultdict


def investigate_sayings():
    # TODO
    # Verbesserung mittels wiki-api - Texte direkt aus Wikipedia "Sprichwörter" auslesen?
    # Tutorial: https://wdqs-tutorial.toolforge.org/index.php/simple-queries/the-simplest-query/basic-sparql-query/
    # Methode "tut" zu viel - Zerlegen in Beschaffung der Daten und Erstellen des Datenmodells
    filename = Path("C:/Users/Carina/Documents/Projkete/WortspielGenerator/Sprueche.txt")
    with open(filename, "r", encoding="UTF-8") as file:
        investigated_sayings = defaultdict(list)
        for line in file:
            splitted = line.strip().split(".\"")

            saying = splitted[0].strip().replace('\"', '')
            if len(saying) == 1:
                continue

            words = saying.split(" ")
            for word in words:
                if word.istitle():
                    investigated_sayings[saying].append(word)
    return investigated_sayings
Beim Zerlegen der Funktion muss ich auch nochmal genau anschauen, was es mit "with open" _genau_ auf sich hat. Es sorgt wohl dafür (so habe ich die Tutorials verstanden), dass die Datei am Ende wieder geschlossen wird.
Ein Dict mit beliebigen Strings als Keys ist IMHO nicht komisch.
Es kann durchaus sein, dass mein "ungutes Gefühl" daher rührt, dass Umlaute in Delphi ein Problem waren, bevor dort Unicode eingeführt wurde. Wenn das in Python kein Problem ist, dann passt das ja :)

Zu
aber `if foo` statt `if foo is not None` schreibe ich nie, weil das auch bei „leeren“ (bzw. allgemein „falsy“) Werten ins `if` springt
Ich fürchte ich muss hier noch "falsy" googeln, denn den Begriff höre/lese ich heute zum ersten Mal.
Oh je :) Ich weiß soviel _nicht_
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@narpfel
@rogerb: Flüchtigkeitsfehler, muss natürlich „nicht ins `if` springt“ heißen. Der Punkt ist, dass mit `if foo` nicht zwischen `None` und allgemein falsy unterscheiden werden kann, deswegen besser `if foo is not None`.
hm... jetzt bin ich etwas verwirrt.
vielleicht liegt's auch daran, dass ich falsy noch nicht kenne.

`if foo is not None`. --> hört sich für meine Ohren "explizit" an. Und wenn explizit besser ist als implizit, wäre das nach meiner laienhaften Auffassung besser. Aber andererseits klingt es so als wäre diese Schreibweise extrem unüblich.

Sorry, dass ich jetzt hier nochmal nachhaken muss. Ich stehe wohl etwas auf der Leitung.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

falsy sind Dinge, die als falsch gewertet werden. Auch wenn sie nicht der False-wert selbst sind. Zb 0, 0.0, “”, {}, [], () sind alle falsch. Man kann das auch selbst überladen auf eigenen Klassen, mit __nonzero__.
Buchfink
User
Beiträge: 193
Registriert: Samstag 11. September 2021, 10:16

@__deets__
vielen lieben Dank für die Erklärung.

Ich hab das hier gefunden (https://developer.mozilla.org/de/docs/Glossary/Falsy) Der Link bezieht sich aber auf JavaScript. Ich hatte auch noch den Beispiel-Code von rogerb ausprobiert. Damit konnte ich es nachvollziehen.
Ich kenne das von Datenbanken so, dass man da aufpassen muss hinsichtlich "Null-Handling".

An "" (leer) hatte ich ehrlich gesagt gar nicht gedacht. Danke für den Hinweis.

Eigentlich möchte ich, dass er nur was in die Liste der substituierten Sprichwörter schreibt, wenn ein Reim gefunden wurde. Wenn aus irgendwelchen Gründen '"" (leer) zurückkäme (oder eben None) soll er nichts tun.

Insofern wäre "if substituted_word:" wohl semantisch besser. Sehe ich das richtig?

Ganz generell muss man meinem obigem Code wohl zum Vorwurf machen, dass er in Punkto Fehlerhandling fragil ist.

LG
Antworten