hallo,
wer mag, kann sich ja mal mein Lernprojekt anschauen.
Es handelt sich um eine Tennis-Liga-Simulation.
Es gibt genau eine Interaktion und zwar während eines Matches.
Ansonsten kann man einfach nur ein bisschen beobachten, wer Meister wird, absteigt und aufsteigt
und vielleicht auf seinen eigenen Spieler Wetten abschließen....
https://gist.github.com/matbo81/5372975
es handelt sich um 4 python-Dateien und 3 csv-Dateien.
die Ziele meines Lernprojektes:
-einfache Einbindung einer Datenbankdatei csv
-flexibles und einfach zu erweiterndes Textmenü
-das Arbeiten mit Objekten
-Spaß haben
viel Spaß
matbo
ein bisschen Spaß an einer Tennis-Liga-Simulation
Hallo matbo,
in Python braucht man keine Getter und Setter und sollte sie der Leserlichkeit wegen auch nicht benutzen. Das Gegenteil (property) kann manchmal nützlich sein.
String sollte man nicht mit + und »str« zusammensetzen. Du hast ja schon gezeigt, dass Du »format« kennst, aber Du solltest auch kein »str« innerhalb »format« benutzen, das ist unnötig.
»PlayerDict.__str__« liefert keinen String zurück.
Du benutzt an seltsamen Stellen Klammern.
in Python braucht man keine Getter und Setter und sollte sie der Leserlichkeit wegen auch nicht benutzen. Das Gegenteil (property) kann manchmal nützlich sein.
String sollte man nicht mit + und »str« zusammensetzen. Du hast ja schon gezeigt, dass Du »format« kennst, aber Du solltest auch kein »str« innerhalb »format« benutzen, das ist unnötig.
»PlayerDict.__str__« liefert keinen String zurück.
Du benutzt an seltsamen Stellen Klammern.
hallo Sirius3,
danke für dein Feedback.
Das man Getter und Setter weglassen sollte, habe ich erst im Laufe des Projektes gelernt. In späteren Codezeilen greife ich dann direkt auf die Attribute zu.
property nehme ich mir mal vor.
danke für dein Feedback.
Das man Getter und Setter weglassen sollte, habe ich erst im Laufe des Projektes gelernt. In späteren Codezeilen greife ich dann direkt auf die Attribute zu.
property nehme ich mir mal vor.
@matbo: Es ist ja nicht so als wenn man einmal geschriebene Getter/Setter nicht auch wieder entfernen könnte.
@matbo: Erster und IMHO sehr wichtiger Kritikpunkt: Es läuft nicht. Du versuchst im `start`-Modul ein `Menu`-Modul zu importieren dass es nicht gibt:
Namen in Python sind „case sensitive”, dass heisst Gross- und Kleinschreibung spielt eine Rolle.
Das `start`-Modul besteht nur aus diesem einen Import und sonst nichts. Damit ist es ziemlich überflüssig. Ausserdem bedeutet es, dass man `menu` nicht importieren kann, ohne dass das Programm abläuft. Module sollte man aber so schreiben, dass man sie ohne Effekte importieren kann. Denn nur dann kann man sie wiederverwenden, einzelne Funktionen oder Klassen (automatisiert) testen, damit „live” in einer Python-Shell herum spielen um sie zu erkunden oder Fehlern interaktiv auf die Spur kommen, und so weiter.
Bei den Kommentaren wird zu viel gebrauch von '#' gemacht. Eines am Anfang der Kommentarzeile reicht völlig aus. Wozu das anhübschen mit vielen '#' führen kann, sieht man an einigen Kommentaren wo der Text anscheinend nachträglich verändert wurde und jetzt diese Kommentarblockrahmen rechts nicht mehr einheitlich abschliessen.
Im `menu`-Modul ist in Zeile 16 eine Zeichenkette die keinen Effekt hat. Wenn das ein Kommentar sein soll, der an *der* Stelle im Quelltext stehen soll, dann bitte wirklich als Kommentar und nicht als Zeichenkette. Falls es der DocString für das Modul sein soll, dann steht er syntaktisch an der falschen Stelle und gehört vor die ``import``-Anweisungen oben im Modul. Vom Inhalt her scheint mir das aber weder das Modul zu beschreiben noch irgend etwas mit den Funktionen zu tun zu haben, die darunter definiert werden‽
Die Namensgebung und die Quelltextformatierung halten sich nicht an den Style Guide for Python Code.
Die Namen sind auch teilweise ziemlich kryptisch. Wenn Du `menu_width` meinst, dann schreib das doch auch statt `mw` unter dem man sich nichts vorstellen kann. Diese Funktion aus dem `Texte`-Modul gibt nur eine Zahl zurück, also eigentlich hätte eine Konstante völlig ausgereicht, statt das man in allen möglichen Funktionen und Methoden `Texte.mw()` aufruft und den Wert dann lokal noch mal an einen Namen bindet. Man hätte das auch besser in einer Klasse gekapselt die Methoden hat um Texte zentriert und mit ”Verzierungen” wie Linien und so weiter auszugeben.
Die erste „Abkürzung” in `menuOptions()` verstehe ich nicht. Warum wird da die Funktion verlassen? So etwas gehört dokumentiert.
Einen Namen sollte man nur für den selben („duck”-)Typ verwenden und nicht wie das `special`-Argument für `False` *oder* für eine Liste (oder allgemein ein iterierbares Objekt). Dann ist der Quelltext leichter verständlich, weniger fehleranfällig, und kann auch vereinfacht werden. Wenn man dort statt `False` einfach eine leere Liste übergeben würde, kann man sich das ``if`` sparen und dieses Argument einfach *immer* als Liste/iterierbares Objekt behandeln. Der Name `special` sagt irgendwie nicht wirklich aus, dass es sich um optionale zusätzliche Kopfinformation für das Menü handelt. Da wäre `header_lines` zum Beispiel treffender, und da es optional ist, sollte man das Argument nach hinten in der Signatur verschieben und als Defaultwert zum Beispiel ein leeres Tupel angeben.
``for i in range(len(sequence)):`` um dann mit der Laufvariablen auf eine oder mehrere Sequenzen per Index zuzugreifen ist in Python ein „anti pattern”. Man kann *direkt* über die Elemente von Sequenzen iterieren, ohne einen Umweg über einen Index. Wenn man *zusätzlich* eine fortlaufende Zahl benötigt, gibt es die `enumerate()`-Funktion. Die man auch bei anderen Startwerten als 0 anfangen lassen kann. Soll „parallel” über mehrere Sequenzen iteriert werden, gibt es die `zip()`-Funktion.
Wenn man über „parallele” Listen itieriert, sollte man sich auch fragen warum das überhaupt nötig ist, denn wenn dabei zusammengehörende Daten in verschiedenen Listen stecken, hat man sehr wahrscheinlich etwas bei der Datenstruktur falsch gemacht.
Der Aufruf von `Texte.turnInfo()` hat in der `menuOptions()`-Funktion IMHO nichts zu suchen, denn dadurch ist das Menü nicht mehr allgemein verwendbar.
Auch in der `menuInput()` verstehe ich den Sinn der ersten beiden Zeilen nicht. Genau so wenig wie die `Texte.hitWords()`-Funktion. Die könnte glatt aus einer Anleitung für möglichst schlechten, verwirrenden Quelltext stammen. Der Name der Funktion ist mir unklar, und einen verständlichen Text mit einem kryptischen Funktionsaufruf mit einer magischen Zahl zu verschleiern ist echt schräg.
Du hast auch an mehreren Stellen ``while``-Schleifen bei denen Namen erst an Dummy-Werte gebunden werden, die erst innerhalb der Schleife an sinnvolle Werte gebunden werden. Das sind eigentlich Schleifen bei denen die Abbruchbedingung *in* der Schleife beziehungsweise oft an deren Ende geprüft werden. Dafür verwendet man in Python eine „Endlos-Schleife” und die ``break``-Anweisung. Beispiel:
Die `menulist` bei der `__init__` der `Menu`-Klasse ist viel zu kompliziert. Da sollten einzelne Argumente übergeben werden statt einer komplexen Datenstruktur. Wenn man so etwas übergeben können möchte, dann stellt man dafür üblicherweise eine Klassenmethode (`classmethod()`) zusätzlich zur Verfügung.
`execs` klingt nach Mehrzahl, es wird dort daran aber nur ein aufrufbares Objekt gebunden — das ist irreführend. Ausserdem gibt es dort auch wieder das Problem, dass entweder ein aufrufbares Objekt *oder* `False` gebunden wird, was an jeder Stelle wo man das Attribut verwenden möchte, einen Test erforderlich macht. Der übliche Wert wenn man „nichts” meint ist nicht `False` sondern `None` und wenn `None` übergeben wurde, sollte in der `__init__` dafür gesorgt werden, dass an das Attribut *in jedem Fall* ein aufrufbares Objekt gebunden wird, damit man beim Verwenden nichts mehr prüfen muss.
Die `update_*`-Methoden müssten eigentlich `set_*` heissen, wenn triviale Getter/Setter in Python nicht sowieso unüblich wären.
Die `make*`-Methoden „machen” nichts in dem Sinne in dem man im englischen das Wort „make” verwendet und auch wenn das deutsche „mache dieses oder jenes” gemeint wäre, dann ist das einfach nur ein allgemeines Füllwort welches man durch eine treffenderes ersetzen sollte, was besser beschreibt was diese Methoden leisten. Beispielsweise `print_options()` und `get_input()`. Da beide Methoden nur den Aufruf von Funktionen enthalten, stellt sich die Frage warum diese Funktionen nicht stattdessen an dieser Stelle stehen.
Diese ``# end-irgendwas``-Kommentare sind eigenartig. Wenn Du Python's Syntax ohne „druckbare” Blockenden nicht magst, dann verwende besser eine andere Programmiersprache. Das Ende sollte man auch ohne solche Kommentare erkennen können.
`MenuController` verwendet in der `__init__` Daten die auf „magische Weise” aus einem anderen Modul genommen werden, statt als Argument übergeben zu werden. Damit ist das `Texte`-Modul viel zu eng an das `menu`-Modul gekoppelt. Das war es bis zu diesem Zeitpunkt zwar auch schon, zum Beispiel durch die `mw()`-Funktion, aber hier ist ein Punkt erreicht der das `menu`-Modul nicht für andere Aufgaben wiederverwendbar macht.
Dabei wird auch wieder eine magische, nichtssagende Zahl verwendet, denn was soll die 2 in ``Texte.menusDict(2)`` aussagen? Was wäre hier die Bedeutung von 0, 1, 3, …?
Was bedeutet „Chall” in `ChallView`?
Das was danach mit den magischen Zahlen mit `self.titles` passiert ist gruselig. Da werden total unnötige Indirektionen über magische Zahlen/Indexe(?) erzeugt, statt eine vernünftige Datenstruktur zu verwenden, wo alle Informationen die zusammengehören auch zusammengefasst gespeichert werden.
Die auskommentierten Debug-Ausgaben kann man eleganter mit dem `logging`-Modul umsetzen. Dann braucht man sie nämlich nicht auskommentieren und kann sie trotzdem je nach Bedarf (de)aktivieren.
In `last_check()` werden Sachen gemacht die nicht objektorientiert sind. Statt in einer riesigen Methode zu testen welchen Menüpunkt man vor sich hat und dann entsprechend etwas zu tun, sollte man einfach eine Methode auf dem gewählten Menüpunkt-Objekt — ein Typ den es in diesem Programm noch nicht gibt — aufrufen, der dann die Aktion selbst durchführt oder aber eine ihm dafür übergebene Funktion oder Methode aufruft.
So, das war's erst einmal für dieses eine Modul. Ein kurzer Blick in das `Texte`-Modul lässt Böses erahnen was die Verwendung von globalen Daten(strukturen) angeht. Da ist sicher noch viel zu tun.
Die (Um)Frage nach der Programmierdauer kann ich nicht beantworten, weil ich es nicht zum Laufen bekomme und damit auch nicht so einfach sehen kann was das Programm eigentlich leistet. Wenn ich den Namen der Menu-Datei korrigiere kommt bei mir das hier:
Code: Alles auswählen
$ python start.py
Traceback (most recent call last):
File "start.py", line 1, in <module>
import Menu
ImportError: No module named Menu
Das `start`-Modul besteht nur aus diesem einen Import und sonst nichts. Damit ist es ziemlich überflüssig. Ausserdem bedeutet es, dass man `menu` nicht importieren kann, ohne dass das Programm abläuft. Module sollte man aber so schreiben, dass man sie ohne Effekte importieren kann. Denn nur dann kann man sie wiederverwenden, einzelne Funktionen oder Klassen (automatisiert) testen, damit „live” in einer Python-Shell herum spielen um sie zu erkunden oder Fehlern interaktiv auf die Spur kommen, und so weiter.
Bei den Kommentaren wird zu viel gebrauch von '#' gemacht. Eines am Anfang der Kommentarzeile reicht völlig aus. Wozu das anhübschen mit vielen '#' führen kann, sieht man an einigen Kommentaren wo der Text anscheinend nachträglich verändert wurde und jetzt diese Kommentarblockrahmen rechts nicht mehr einheitlich abschliessen.
Im `menu`-Modul ist in Zeile 16 eine Zeichenkette die keinen Effekt hat. Wenn das ein Kommentar sein soll, der an *der* Stelle im Quelltext stehen soll, dann bitte wirklich als Kommentar und nicht als Zeichenkette. Falls es der DocString für das Modul sein soll, dann steht er syntaktisch an der falschen Stelle und gehört vor die ``import``-Anweisungen oben im Modul. Vom Inhalt her scheint mir das aber weder das Modul zu beschreiben noch irgend etwas mit den Funktionen zu tun zu haben, die darunter definiert werden‽
Die Namensgebung und die Quelltextformatierung halten sich nicht an den Style Guide for Python Code.
Die Namen sind auch teilweise ziemlich kryptisch. Wenn Du `menu_width` meinst, dann schreib das doch auch statt `mw` unter dem man sich nichts vorstellen kann. Diese Funktion aus dem `Texte`-Modul gibt nur eine Zahl zurück, also eigentlich hätte eine Konstante völlig ausgereicht, statt das man in allen möglichen Funktionen und Methoden `Texte.mw()` aufruft und den Wert dann lokal noch mal an einen Namen bindet. Man hätte das auch besser in einer Klasse gekapselt die Methoden hat um Texte zentriert und mit ”Verzierungen” wie Linien und so weiter auszugeben.
Die erste „Abkürzung” in `menuOptions()` verstehe ich nicht. Warum wird da die Funktion verlassen? So etwas gehört dokumentiert.
Einen Namen sollte man nur für den selben („duck”-)Typ verwenden und nicht wie das `special`-Argument für `False` *oder* für eine Liste (oder allgemein ein iterierbares Objekt). Dann ist der Quelltext leichter verständlich, weniger fehleranfällig, und kann auch vereinfacht werden. Wenn man dort statt `False` einfach eine leere Liste übergeben würde, kann man sich das ``if`` sparen und dieses Argument einfach *immer* als Liste/iterierbares Objekt behandeln. Der Name `special` sagt irgendwie nicht wirklich aus, dass es sich um optionale zusätzliche Kopfinformation für das Menü handelt. Da wäre `header_lines` zum Beispiel treffender, und da es optional ist, sollte man das Argument nach hinten in der Signatur verschieben und als Defaultwert zum Beispiel ein leeres Tupel angeben.
``for i in range(len(sequence)):`` um dann mit der Laufvariablen auf eine oder mehrere Sequenzen per Index zuzugreifen ist in Python ein „anti pattern”. Man kann *direkt* über die Elemente von Sequenzen iterieren, ohne einen Umweg über einen Index. Wenn man *zusätzlich* eine fortlaufende Zahl benötigt, gibt es die `enumerate()`-Funktion. Die man auch bei anderen Startwerten als 0 anfangen lassen kann. Soll „parallel” über mehrere Sequenzen iteriert werden, gibt es die `zip()`-Funktion.
Wenn man über „parallele” Listen itieriert, sollte man sich auch fragen warum das überhaupt nötig ist, denn wenn dabei zusammengehörende Daten in verschiedenen Listen stecken, hat man sehr wahrscheinlich etwas bei der Datenstruktur falsch gemacht.
Der Aufruf von `Texte.turnInfo()` hat in der `menuOptions()`-Funktion IMHO nichts zu suchen, denn dadurch ist das Menü nicht mehr allgemein verwendbar.
Auch in der `menuInput()` verstehe ich den Sinn der ersten beiden Zeilen nicht. Genau so wenig wie die `Texte.hitWords()`-Funktion. Die könnte glatt aus einer Anleitung für möglichst schlechten, verwirrenden Quelltext stammen. Der Name der Funktion ist mir unklar, und einen verständlichen Text mit einem kryptischen Funktionsaufruf mit einer magischen Zahl zu verschleiern ist echt schräg.
Du hast auch an mehreren Stellen ``while``-Schleifen bei denen Namen erst an Dummy-Werte gebunden werden, die erst innerhalb der Schleife an sinnvolle Werte gebunden werden. Das sind eigentlich Schleifen bei denen die Abbruchbedingung *in* der Schleife beziehungsweise oft an deren Ende geprüft werden. Dafür verwendet man in Python eine „Endlos-Schleife” und die ``break``-Anweisung. Beispiel:
Code: Alles auswählen
#
# anstatt:
#
spam = None
while spam != 'end':
spam = do_something()
#
# besser:
#
while True:
spam = do_something()
if spam == 'end':
break
`execs` klingt nach Mehrzahl, es wird dort daran aber nur ein aufrufbares Objekt gebunden — das ist irreführend. Ausserdem gibt es dort auch wieder das Problem, dass entweder ein aufrufbares Objekt *oder* `False` gebunden wird, was an jeder Stelle wo man das Attribut verwenden möchte, einen Test erforderlich macht. Der übliche Wert wenn man „nichts” meint ist nicht `False` sondern `None` und wenn `None` übergeben wurde, sollte in der `__init__` dafür gesorgt werden, dass an das Attribut *in jedem Fall* ein aufrufbares Objekt gebunden wird, damit man beim Verwenden nichts mehr prüfen muss.
Die `update_*`-Methoden müssten eigentlich `set_*` heissen, wenn triviale Getter/Setter in Python nicht sowieso unüblich wären.
Die `make*`-Methoden „machen” nichts in dem Sinne in dem man im englischen das Wort „make” verwendet und auch wenn das deutsche „mache dieses oder jenes” gemeint wäre, dann ist das einfach nur ein allgemeines Füllwort welches man durch eine treffenderes ersetzen sollte, was besser beschreibt was diese Methoden leisten. Beispielsweise `print_options()` und `get_input()`. Da beide Methoden nur den Aufruf von Funktionen enthalten, stellt sich die Frage warum diese Funktionen nicht stattdessen an dieser Stelle stehen.
Diese ``# end-irgendwas``-Kommentare sind eigenartig. Wenn Du Python's Syntax ohne „druckbare” Blockenden nicht magst, dann verwende besser eine andere Programmiersprache. Das Ende sollte man auch ohne solche Kommentare erkennen können.
`MenuController` verwendet in der `__init__` Daten die auf „magische Weise” aus einem anderen Modul genommen werden, statt als Argument übergeben zu werden. Damit ist das `Texte`-Modul viel zu eng an das `menu`-Modul gekoppelt. Das war es bis zu diesem Zeitpunkt zwar auch schon, zum Beispiel durch die `mw()`-Funktion, aber hier ist ein Punkt erreicht der das `menu`-Modul nicht für andere Aufgaben wiederverwendbar macht.
Dabei wird auch wieder eine magische, nichtssagende Zahl verwendet, denn was soll die 2 in ``Texte.menusDict(2)`` aussagen? Was wäre hier die Bedeutung von 0, 1, 3, …?
Was bedeutet „Chall” in `ChallView`?
Das was danach mit den magischen Zahlen mit `self.titles` passiert ist gruselig. Da werden total unnötige Indirektionen über magische Zahlen/Indexe(?) erzeugt, statt eine vernünftige Datenstruktur zu verwenden, wo alle Informationen die zusammengehören auch zusammengefasst gespeichert werden.
Die auskommentierten Debug-Ausgaben kann man eleganter mit dem `logging`-Modul umsetzen. Dann braucht man sie nämlich nicht auskommentieren und kann sie trotzdem je nach Bedarf (de)aktivieren.
In `last_check()` werden Sachen gemacht die nicht objektorientiert sind. Statt in einer riesigen Methode zu testen welchen Menüpunkt man vor sich hat und dann entsprechend etwas zu tun, sollte man einfach eine Methode auf dem gewählten Menüpunkt-Objekt — ein Typ den es in diesem Programm noch nicht gibt — aufrufen, der dann die Aktion selbst durchführt oder aber eine ihm dafür übergebene Funktion oder Methode aufruft.
So, das war's erst einmal für dieses eine Modul. Ein kurzer Blick in das `Texte`-Modul lässt Böses erahnen was die Verwendung von globalen Daten(strukturen) angeht. Da ist sicher noch viel zu tun.
Die (Um)Frage nach der Programmierdauer kann ich nicht beantworten, weil ich es nicht zum Laufen bekomme und damit auch nicht so einfach sehen kann was das Programm eigentlich leistet. Wenn ich den Namen der Menu-Datei korrigiere kommt bei mir das hier:
Code: Alles auswählen
$ python3 start.py
Traceback (most recent call last):
File "start.py", line 1, in <module>
import Menu
File "/home/bj/tmp/affsaison01/Menu.py", line 1, in <module>
from AffSaison import game
File "/home/bj/tmp/affsaison01/AffSaison.py", line 867, in <module>
game = Game()
File "/home/bj/tmp/affsaison01/AffSaison.py", line 752, in __init__
self.init_saison()
File "/home/bj/tmp/affsaison01/AffSaison.py", line 787, in init_saison
liga.add_turnier(name, punkte, time, self)
File "/home/bj/tmp/affsaison01/AffSaison.py", line 509, in add_turnier
self.playersToTurnier(tName)
File "/home/bj/tmp/affsaison01/AffSaison.py", line 512, in playersToTurnier
self.turnierListe[tu].set_players(self.standings)
File "/home/bj/tmp/affsaison01/AffSaison.py", line 367, in set_players
self.players = new.copy()
AttributeError: 'list' object has no attribute 'copy'
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Nicht angewiesen, aber man gewinnt damit Freiheiten beim API-Design, da man einfach Code zu den Gettern/Settern hinzufuegen kann, ohne dass sich fuer den Nutzer etwas aendert. Bei Gettern z.B. Logging, bei Settern z.B. Validierung. In Python kommt man wegen Properties ohne diesen Umweg aus.kevind hat geschrieben:Ist man in anderen Programmiersprachen auf "getter/setter" angewiesen ? Oder welchen Sinn haben die eigentlich ?
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Getter- und Setter-Funktionen verwendet man beispielsweise in Java (sehr exzessiv), C++ und anderen Sprachen, welche keine Properties kennen. In diesen vermeidet man öffentliche Member gänzlich und deklariert diese privat (= außerhalb der Klasse nicht ansprechbar). Um dennoch auf diese zugreifen zu können, wer die vorgenannten Funktionen verwendet.
Python kennt jedoch keine privaten und öffentlichen Attribute und es hat properties. Daher ist es auch nicht sinnvoll und nötig, Getter und Setter zu verwenden.
Grüße ... bwbg
Python kennt jedoch keine privaten und öffentlichen Attribute und es hat properties. Daher ist es auch nicht sinnvoll und nötig, Getter und Setter zu verwenden.
Grüße ... bwbg
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Aus Präzisionsgründen: Das sind keine Klassenattribute. Das sind Attribute eines Exemplars (einer Instanz) der Klasse.kevind hat geschrieben:Aber hier werden doch sowieso nur Klassen-attribute zurückgegeben ?
@BlackJack
danke BlackJack für die vielen Anmerkungen.
Das ist einer der Gründe warum ich diesen "Programmschlamassel" mal hier gepostet habe, der aber immerhin bei mir funktioniert.
Gut, den Menudateinamen habe ich jetzt groß geschrieben, damit dürfte der Fehler weg sein.
deine letzte Fehlermeldung ('list' object has no attribute 'copy') habe ich auch einmal erhalten, als ich das Programm probehalber mit python 2.7 gestartet habe. Ansonsten in der aktuellen 3.3.1 Version läuft es zumindest bei mir. Schade, dafür.
Das "Texte"-Modul ist sicher noch schlimmer, es ist ein Ansammlung an Hilfe-Classes und -Funktionen.
Ich denke, man sieht ganz klar, dass ich das Programm ohne vorher angefertigtes Game Design und mit viel Eigeninterpretationen und Viertelwissen von Konzepten geschrieben habe.
Aber deine Punkte werde ich mir zu Herzen, z.B. die undeutlichen Bezeichnungen, die Vermeidung von Iterationen mit Laufvariablen, das "logging" Modul, auf Mehrverwendbarkeit von Modulen zu achten und, und, und,...
so viel Arbeit hast du dir beim Analysieren gegeben und dann kamst du nicht mal in den Genuss des Spiels...
danke BlackJack für die vielen Anmerkungen.
Das ist einer der Gründe warum ich diesen "Programmschlamassel" mal hier gepostet habe, der aber immerhin bei mir funktioniert.
Gut, den Menudateinamen habe ich jetzt groß geschrieben, damit dürfte der Fehler weg sein.
deine letzte Fehlermeldung ('list' object has no attribute 'copy') habe ich auch einmal erhalten, als ich das Programm probehalber mit python 2.7 gestartet habe. Ansonsten in der aktuellen 3.3.1 Version läuft es zumindest bei mir. Schade, dafür.
Das "Texte"-Modul ist sicher noch schlimmer, es ist ein Ansammlung an Hilfe-Classes und -Funktionen.
Ich denke, man sieht ganz klar, dass ich das Programm ohne vorher angefertigtes Game Design und mit viel Eigeninterpretationen und Viertelwissen von Konzepten geschrieben habe.
Aber deine Punkte werde ich mir zu Herzen, z.B. die undeutlichen Bezeichnungen, die Vermeidung von Iterationen mit Laufvariablen, das "logging" Modul, auf Mehrverwendbarkeit von Modulen zu achten und, und, und,...
so viel Arbeit hast du dir beim Analysieren gegeben und dann kamst du nicht mal in den Genuss des Spiels...
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Wobei AFAIK Alan Kay von dieser Praxis nicht so begeistert ist, weil man damit letztendlich die privaten Attribute doch wieder publiziert.bwbg hat geschrieben:Getter- und Setter-Funktionen verwendet man beispielsweise in Java (sehr exzessiv), C++ und anderen Sprachen, welche keine Properties kennen. In diesen vermeidet man öffentliche Member gänzlich und deklariert diese privat (= außerhalb der Klasse nicht ansprechbar). Um dennoch auf diese zugreifen zu können, wer die vorgenannten Funktionen verwendet.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Wenn man einen Getter für eine Instanzvariable schreibt will man diese ja bewusst publizieren, daher verstehe ich diesen Einwand nicht so ganz. Für eine Instanzvariable die ich nicht publizieren will schreibe ich ja auch keinen Getter.Leonidas hat geschrieben:Wobei AFAIK Alan Kay von dieser Praxis nicht so begeistert ist, weil man damit letztendlich die privaten Attribute doch wieder publiziert.
Das gleiche gilt für Setter.
Der größte Vorteil m. E. wenn man bei anderen Sprachen (wie Java) Getter und Setter verwendet ist, dass man z. B. eine Berechtigungsprüfung (Getter) oder eine Datenvalidierung (Setter) "nachrüsten" kann ohne, dass der Benutzer der Klasse alle Verwendungsstellen anpassen muss.
@trvhgoy: Die Argumentation gegen triviale Getter *und* Setter ist, dass man dadurch internen Zustand nach aussen gibt. Man kann also den Wert abfragen, verändern, und wieder zurück schreiben, wo Kay eher eine Methode auf dem Objekt erwarten würde, welche den internen Zustand verändert.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Der Einwand von Kay war, dass man Klassen über ihre Oparationen modifizieren soll, also ``konto1.überweise(konto2)`` statt ``konto1.set_kontostand(konto1.get_kontostand() - X); konto2.set_kontostand(konto2.get_kontostand() + X)`` und nicht über ihre Variablen arbeiten soll.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack hat geschrieben:@trvhgoy: Die Argumentation gegen triviale Getter *und* Setter ist, dass man dadurch internen Zustand nach aussen gibt. Man kann also den Wert abfragen, verändern, und wieder zurück schreiben, wo Kay eher eine Methode auf dem Objekt erwarten würde, welche den internen Zustand verändert.
Aso, so war das gemeint. Da habt ihr / Alan Kay natürlich recht.Leonidas hat geschrieben:Der Einwand von Kay war, dass man Klassen über ihre Oparationen modifizieren soll, also ``konto1.überweise(konto2)`` statt ``konto1.set_kontostand(konto1.get_kontostand() - X); konto2.set_kontostand(konto2.get_kontostand() + X)`` und nicht über ihre Variablen arbeiten soll.
Diese Verwendung von Gettern / Settern entspricht nicht dem Gedanken der hinter OOP steht.