Seite 3 von 5
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 10:39
von Buchfink
@rogerb
Beim zweiten Hinschauen, würde ich vielleicht ganz auf das Erstellen dieser Datenstruktur verzichten
für mich steht in erster Näherung die Auseinandersetzung mit Pyhton im Vordergrund. Der Weg ist sozusagen das Ziel.
Es gibt viele Aspekte (wie z.B. Falsy oder yield) die ich bisher gar nicht kenne oder die ich zwar ggf. auf den ersten Blick glaube zu verstehen, bei denen sich mir aber der Einsatzzweck nicht sofort erschließt.
Was ich sagen will ist: Vermutlich wird jeder neue Entwurf, den ich mache (und poste), dazu führen, dass man wieder etwas erkennt, was man verbessern könnte.
"investigated_sayings" enthält keine zusätzliche Informationen. Du verbindest lediglich Daten, die zusammengehören in einer neuen Datenstruktur.
Die Idee war, erst mal die Daten ein wenig zu zerlegen (Datenmodell aufbauen). Im zweiten Schritt dann irgendwas auf Basis der Zerlegung zu tun (Substitution) und im dritten Schritt eine Ausgabe der geänderten Daten zu machen.
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 10:47
von Buchfink
@__blackjack__
Und `print()` wäre eher Logging, wenn es keine Ausnahmen sein sollen. Standardbibliothek oder `loguru`.
danke für den Hinweis mit loguru
https://loguru.readthedocs.io/en/stable/overview.html
Das probiere ich mal aus.
Aber was genau meinst du mit "Standardbibliothek"?
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 10:54
von __deets__
Standardbibliothek ist was Python mitbringt. loguru ist nicht darin enthalten & muss installiert werden.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 11:15
von Buchfink
@__deets__
ok, danke. Ich fürchte, ich habe hier den Kontext der Aussage nicht verstanden. Bzw. nach nochmaligem Lesen stelle ich fest, dass meine Frage unpräzise formuliert war.
ich vermute:
Standardbibliothek bezieht sich auf den print()-Befehl?
Bzw. ein Logging kann man entweder mit print (also über die Standardbibliothek) realisieren oder eben über eine Spezialbibliothek wie z.B. loguru.
Habe ich das korrekt verstanden?
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 11:24
von rogerb
@Buchfink,
Standardbibliothek ist dies:
https://docs.python.org/3/library/index.html
und da ist schon eine Grundfunktionalität für logging vorhanden:
https://docs.python.org/3/library/logging.html
Das kannst du also schon verwenden wenn du Python frisch installiert hast, und keine "pip-installierten" Pakete hinzugefügt wurden.
Loguru muss "pip-installiert" werden.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 11:37
von Buchfink
@rogerb
und da ist schon eine Grundfunktionalität für logging vorhanden:
ok -

danke!
genau diese Info hat mir im Hinblick auf den Kontext gefehlt.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 21:15
von Buchfink
hallo @rogerb
das meintest Du mit Generatoren?
Code: Alles auswählen
def substitute_with_rhymes(investigated_sayings):
for key, value in investigated_sayings.items():
for word in value:
substituted_word = get_rhyme(word)
if substituted_word:
yield key.replace(word, substituted_word)
def show_sayings(sayings):
for saying in sayings:
print(saying)
# print(f"Anzahl {len(sayings)}")
Ich musste mehrere Tutorials dazu hören/lesen, um das einigermaßen zu kapieren. Daher hat es ein wenig gedauert. Es ist einfacher irgendwelche bekannten Konzepte zu transferieren. Bei gänzlich neuen Konzepten fehlt mir echt noch die Übung. Daher vielen Dank nochmals für den Tipp mit den Generatoren.
Ich vermute, dass ich das in def investigate_sayings(): auch nutzen könnte. Korrekt?
Die Zeile "print(f"Anzahl {len(sayings)}")" muss dann entfallen, so wie ich das sehe, denn ein Generator ist ja sozusagen eine Form der Optimierung, bei der keine "Gesamtliste" in dem Sinne mehr entsteht.
Ist mein Verständnis soweit korrekt?
Die Gesamtzahl brauche ich aber ohnehin nicht, daher kann das raus. Es war nur eine sehr rudimentäre Form, um zu sehen, ob mein Algorithmus grundsätzlich funktioniert. Ich sollte wohl besser zum Testen des Algorithmus einen Unit-Test schreiben.
Eigentlich soll man ja zuerst Tests schreiben. Daher überlege ich, bevor ich weitere Code-Änderungen mache, mal Unit-Tests zu probieren.
Wie würdet Ihr vorgehen?
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 23:14
von rogerb
Buchfink hat geschrieben: Dienstag 2. November 2021, 21:15
so wie ich das sehe, denn ein Generator ist ja sozusagen eine Form der Optimierung, bei der keine "Gesamtliste" in dem Sinne mehr entsteht.
Ist mein Verständnis soweit korrekt?
Ja, soweit richtig. Ein Generator ist eine besondere Art von Iterator, der beim Iterieren immer nur den nächsten Rückgabewert abgibt anstatt eine ganze Sequenz von Elementen zu erzeugen.
Vereinfacht gesagt, er tut nur das eben nötigste, daher auch der Ausdruck "Lazy evaluation"
Der Generator gibt über yield einen Wert zurück, merkt sich aber, die Stelle, so dass er beim nächsten Anstoß genau nach dem yield weiter arbeiten kann.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Dienstag 2. November 2021, 23:22
von Buchfink
@rogerb
Der Generator gibt über yield einen Wert zurück, merkt sich aber, die Stelle, so dass er beim nächsten Anstoß genau nach dem yield weiter arbeiten kann.
vielen Dank für diese Erläuterung

Re: Code-Review zur Thematik "Konstanten"
Verfasst: Samstag 6. November 2021, 22:23
von Buchfink
@__blackjack__
zu folgender Codezeile habe ich noch eine Frage:
Im Bezeichner "_" steht der Teil der Zeile, der nach dem Trenner '."' kommt.
Theoretisch hätte man ihn auch mit z. B. "additional_info" benennen können.
Ich vermute, dass der Underscore sagen soll, dass der dritte Teil nicht weiter verwendet wird.
Ist der Unterscore in solchen Fällen eine Art Konvention? (Ich habe leider per google bzw. auch in PEP 8 nichts dazu gefunden)
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Samstag 6. November 2021, 23:12
von rogerb
@Buchfink,
hier findest du etwas dokumentiert:
https://docs.python.org/3.10/reference/ ... dentifiers
Zu beachten ist der Unterschied zwischen Interaktive- und Nichtinteraktiv Mode.
Ansonsten wird der Unterstrich auch "don't care" Variable bezeichnet. Wie du schon sagst, zum entpacken in mehrere Variablen, wobei eine nicht interessiert.
Man kann auch mehrere Teile eines Tuple aufsammeln, wenn man nur weiß, dass es mindestens ein Element gibt.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 10:56
von Buchfink
@rogerb
vielen Dank.
Zu meinem Bedauern habe ich gestern
viewtopic.php?f=1&t=53356 völlig überlesen/nicht gefunden, denn dort hast Du eine ähnlich gelagerte Frage ja bereits kurz zuvor beantwortet. Entschuldige bitte.
Ich habe es heute in der Früh erst bemerkt.
Mit dem Stichwort "Wegwerfvariable" bzw. "Don't care Variable" habe ich dann heute morgen auch etliche hilfreiche Treffer bei Google gehabt.
Danke übrigens auch für den Tipp mit *_ für das Aufsammeln von Werten eines Tuples.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 15:26
von Buchfink
@rogerb
Zu beachten ist der Unterschied zwischen Interaktive- und Nichtinteraktiv Mode.
Ist bzgl. der genannten Quelle (
https://docs.python.org/3.10/reference/ ... dentifiers) mit "Interaktive" der Satz folgende Satz gemeint?
Separat stellt der interaktive Interpreter das Ergebnis der letzten Auswertung in der Variablen zur Verfügung.
Ich habe das auf der Python-Console wie folgt mal nachvollzogen:
Mit "Nichtinteraktiv Mode" ist dann die Verwendung im Sinne von "Es wird auch häufig für nicht verwendete Variablen verwendet." gemeint. Ist mein Verständnis soweit korrekt?
Ich möchte nur sichergehen, dass ich alles richtig verstanden habe.
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 15:48
von pillmuncher
Im interaktiven Modus - also in der Python Shell - hat _ eine besondere Bedeutung. In Modulen ist es ein normaler Name wie jeder andere auch.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 16:10
von Buchfink
@pillmuncher
ok vielen Dank.
Ich habe sowohl die Begriffe "Python Shell" als auch "Python Console" in Kontext "interaktiver Modus" gefunden (In PyCharm heißt der Bereich anscheinend "Python Console", daher hatte ich diesen Begriff gewählt)
Ich gehe davon aus, dass beide Begriffe synonym sind.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 16:45
von __blackjack__
Wenn man Korinthen ausscheiden möchte: Console ist das wo der Text drin angezeigt wird, und die Python-Shell ist das Programm, das in diesem Fall über die Konsole mit dem Benutzer kommuniziert. Für den Benutzer sieht das in der Regel nach einer Einheit aus, darum kann man das in der Regel synonym verwenden.
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Sonntag 7. November 2021, 17:03
von Buchfink
verstehe

Re: Code-Review zur Thematik "Konstanten"
Verfasst: Samstag 11. Dezember 2021, 18:53
von Buchfink
Hallo zusammen,
die letzten Wochen musste ich etwas umpriorisieren. Das Spaßprojekt "Wortspielgenerator" ist daher nach hinten gerutscht.
Ich habe nun wieder etwas mehr Zeit und daher mal das Logging eingebaut und wollte gern von Euch eine Meinung hören. Was würdet ihr verbessern?
Code: Alles auswählen
def investigate_sayings():
# TODO
# Verbesserung mittels wiki-api - Texte direkt aus Wikipedia "Sprichwörter" auslesen?
# Tutorials:
# - https://wdqs-tutorial.toolforge.org/index.php/simple-queries/the-simplest-query/basic-sparql-query/
# - https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
# Methode "tut" zu viel - Zerlegen in Beschaffung der Daten und Erstellen des Datenmodells
filename_sayings = Path("Daten/WortspielGenerator/Sprueche_raw.txt")
path_log = Path("Daten/WortspielGenerator/logs/")
path_log.mkdir(parents=True, exist_ok=True)
filename_log = Path("Daten/WortspielGenerator/logs/Sprueche_ausgemustert.txt")
logging.basicConfig(filename=str(filename_log), level=logging.DEBUG)
with open(filename_sayings, "r", encoding="UTF-8") as file:
investigated_sayings = defaultdict(list)
for line_number, line in enumerate(file, 1):
if line.startswith('"'):
saying, seperator, _ = line[1:].partition('"')
if seperator:
for word in saying.split():
if word.istitle():
investigated_sayings[saying].append(word)
else:
logging.debug(f"Fehler: Ende von Spruch in Zeile {line_number} nicht gefunden: {line.strip()}")
else:
line = line.rstrip()
if not (len(line) == 1 and line.isalpha()):
logging.debug(f"Fehler: Unerwartete(s) Zeichen in Zeile {line_number}: {line}.")
return investigated_sayings
1) Findet ihr die Methode zu lang?
2) Ist die Verschachtelungstiefe (noch) ok?
3) Kann man erkennen, was da passiert?
4) Teile des Pfades zur Log-Datei sind redundant. Würde sich der Pfad ändern, müsste man zwei Stellen ändern. Das ist natürlich nicht gut. Eine Konstante erscheint mir in diesem Kontext falsch. Würde man hier einen formatierten String nutzen? Gibt's andere Wege?
5) Sollte man hier ggf. auch einen Generator nutzen?
Ich hatte mir noch folgende Alternative überlegt:
Code: Alles auswählen
def investigate_sayings_alternative():
# TODO
# Verbesserung mittels wiki-api - Texte direkt aus Wikipedia "Sprichwörter" auslesen?
# Tutorials:
# - https://wdqs-tutorial.toolforge.org/index.php/simple-queries/the-simplest-query/basic-sparql-query/
# - https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
# Methode "tut" zu viel - Zerlegen in Beschaffung der Daten und Erstellen des Datenmodells
filename_sayings = Path("Daten/WortspielGenerator/Sprueche_raw.txt")
path_log = Path("Daten/WortspielGenerator/logs/")
path_log.mkdir(parents=True, exist_ok=True)
filename_log = Path("Daten/WortspielGenerator/logs/Sprueche_ausgemustert.txt")
with open(filename_sayings, "r", encoding="UTF-8") as file:
investigated_sayings = defaultdict(list)
for line_number, line in enumerate(file, 1):
investigate_saying(line, line_number, filename_log, investigated_sayings)
return investigated_sayings
def investigate_saying(line, line_number, filename_log, investigated_sayings):
logging.basicConfig(filename=str(filename_log), level=logging.DEBUG)
if line.startswith('"'):
saying, seperator, _ = line[1:].partition('"')
if seperator:
for word in saying.split():
if word.istitle():
investigated_sayings[saying].append(word)
else:
logging.debug(f"Fehler: Ende von Spruch in Zeile {line_number} nicht gefunden: {line.strip()}")
else:
line = line.rstrip()
if not (len(line) == 1 and line.isalpha()):
logging.debug(f"Fehler: Unerwartete(s) Zeichen in Zeile {line_number}: {line}.")
Allerdings stört mich die Liste der übergebenen Parameter. Irgendwie sind die nicht zusammenhängend und semantisch auch nicht gut lesbar. (Leider bin ich mir unsicher, ob man verstehen kann, was ich meine. Bitte gerne nachfragen)
Einziger Vorteil ist, dass die Alternative eine geringere Verschachtelungstiefe hat und die Methoden nicht so lang sind.
Tja nun. Ich bin gespannt auf Eure Anmerkungen.
Am Rande:
Ich würde die Log-Datei gerne auf ".log" enden lassen. Allerdings kann man sie dann in PyCharm nicht mehr anzeigen lassen. Hat jemand eine Idee, warum das so ist?
LG
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Samstag 11. Dezember 2021, 19:11
von Sirius3
Das Logging wird für das ganze Programm konfiguriert, nicht für einzelne Funktionen, basicConfig hat also in dieser Funktion nichts verloren.
filename_log sollte eine Konstante sein, und path_log gar nicht existieren.
Für das eigentliche Logging erstellt man einen Logger.
Fehler sollten error-Logs sein, und kein debug.
Code: Alles auswählen
import logging
from pathlib impot Path
logger = logging.getLogger(__name__)
LOG_FILENAME = Path("Daten/WortspielGenerator/logs/Sprueche_ausgemustert.txt")
def initialize_logging():
LOG_FILENAME.parent.mkdir(parents=True, exist_ok=True)
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
def investigate_sayings(filename):
with filename.open(encoding="UTF-8") as file:
sayings = defaultdict(list)
for line_number, line in enumerate(file, 1):
if line.startswith('"'):
saying, seperator, _ = line[1:].partition('"')
if seperator:
for word in saying.split():
if word.istitle():
sayings[saying].append(word)
else:
logger.error(f"Fehler: Ende von Spruch in Zeile {line_number} nicht gefunden: {line.strip()}")
else:
line = line.rstrip()
if not (len(line) == 1 and line.isalpha()):
logger.error(f"Fehler: Unerwartete(s) Zeichen in Zeile {line_number}: {line}.")
return sayings
def main():
initialize_logging()
filename_sayings = Path("Daten/WortspielGenerator/Sprueche_raw.txt")
sayings = investigated_sayings(filename_sayings)
...
Wenn Dir die Funktion zu komplex ist, dann ist eine Aufteilung in Lesen und Aufteilen nach Wörtern sinnvoll:
Code: Alles auswählen
def read_sayings(filename):
with filename.open(encoding="UTF-8") as file:
for line_number, line in enumerate(file, 1):
if line.startswith('"'):
saying, seperator, _ = line[1:].partition('"')
if seperator:
yield saying
else:
logger.error(f"Fehler: Ende von Spruch in Zeile {line_number} nicht gefunden: {line.strip()}")
else:
line = line.rstrip()
if not (len(line) == 1 and line.isalpha()):
logger.error(f"Fehler: Unerwartete(s) Zeichen in Zeile {line_number}: {line}.")
def investigate_sayings(filename):
sayings = defaultdict(list)
for saying in read_sayings(filename):
for word in saying.split():
if word.istitle():
sayings[saying].append(word)
return sayings
Re: Code-Review zur Thematik "Konstanten"
Verfasst: Samstag 11. Dezember 2021, 19:21
von Buchfink
@Sirius3
vielen Dank! Ich werde mir das heute noch anschauen.