In C würde ich Zeiger dafür benutzen ...

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.
Antworten
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

... in Python natürlich nicht ;) Aber, was löst das folgende Problem:

Über einen Dialog möchte ich einen Namen einlesen und weiterverarbeiten. Ich stelle mir eine Klasse vor, von der ich bei bedarf eine Instanz erstelle und den Wert direkt als Ergebnis des Aufrufs zu bekommen:

name = C_DlgClass()

Allerdings wird 'name' hier jetzt natürlich eine Instanz der Klasse enthalten. In C++ würde ich beim Erzeugen der Instanz einfach einen Zeiger oder eine Referenz auf 'name' übergeben.

C_DlgClass( *name)

Gibt es in Python einen entsprechenden Mechanismus bzw. wie löse ich die Aufgabe?

Ich könnte natürlich eine globale Instanz einer solchen Klasse erstellen und dann immer eine Methode davon aufrufen, die den Dialog dann erstellt und den gelesenen Text dann zurück gibt.
Oder ich könnte aus 'name' eine Klasse machen und dann einfach ein Attribut von 'name' ändern, aber das finde ich etwas übertrieben.

Für eine andere Idee bin ich natürlich dankbar, aber ich würde trotzdem gern wissen, wie man das geschilderte Problem löst.

Gruß und Danke,

Christoph
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Zu deinem Python-Beispiel: Wenn du ein solches Verhalten willst, dann erstellst du einfach eine Funktion und keine Klasse. Die Funktion kann dann doch beliebigen Code ausführen. Zum Beispiel einen Dialog erzeugen und dessen Ergebnis zurückliefern. Oder du gibst der Dialog-Klasse einfach ein entsprechendes Attribut.

Zu deinem C++-Beispiel: Das würde in C++ auch niemand so lösen, das ist viel zu unflexibel und bringt keine Vorteile. Wenn der Dialog im Konstruktur angezeigt wird, dann macht man bereits einen Fehler. Und wenn man es nicht tut, dann benötigt es eh eine weitere Funktion oder Methode auf dem Dialog. Oder implementiert am besten gleich das MVC-Pattern.

Verrate mal ein wenig mehr, was du eigentlich machen möchtest. Wenn dein Programm komplexer werden sollte, dann böte sich unter Umständen eine Lösung über MVC an, möglicherweise lässt es sich aber auch ganz trivial lösen.

Du solltest auch noch an deiner Namensgebung arbeiten. Bei C_DlgClass läuft es einem ja eiskalt den Rücken runter. Nicht nur, dass niemand mehr die ungarische Notation verwendet (das war für so etwas auch gar nicht vorgesehen und in Python geht es schon gar nicht), du gehst auch noch extra sicher und hängst hinten ein "Class" dran. "Dialog" hat genau so viel Aussagekraft. Zu Python solltest du dir daher mal PEP 8 anschauen. Ansonsten darfst du natürlich auch gerne Vokale verwenden. "Dialog" ist einfach eindeutiger als "Dlg" und auf zwei eingesparte Zeichen kommt es dir hoffentlich nicht drauf an ;-)
Das Leben ist wie ein Tennisball.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Hey Du ;),

danke für die Tips. Manchmal ist man wie vernagelt, natürlich hätte es eine Funktion auch getan (hier käme jetzt der vor-die-Stirn-klatsch Smiley hin). Irgendwie war ich auf 'ne Klasse fixiert...

Es geht um nichts besonderes, ein kleines Progrämmchen bei dem ich mir die Frage eben gestellt habe, reine Neugierde sozusagen.

Was die Benamsung angeht: Natürlich braucht eine Klasse einen Namen, der was taugt. In diesem Fall ist der Name aber relativ korrekt gewählt, denn es geht um eine Klasse, die einen allgemenien Dialog darstellt und das hinten stehende 'Class' betont das eben noch. Das 'C_' schreibe ich aus Prinzip dazu. Ich gebe Dir aber Recht: In einem normalen Programm hat sowas genau gar nichts verloren.

Bei Siemens soll es übrigends mal eine Richtlinie zur Findung von Abkürzungen gegeben haben, eine der ersten Regeln war: Laß die Vokale weg... 8).

Gruß,

Christoph
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Meine Frage ist beantwortet, daher:

OT OT OT

'Tschuldige, Du hast einen Nerv getroffen :shock:.
EyDu hat geschrieben:Du solltest auch noch an deiner Namensgebung arbeiten. Bei C_DlgClass läuft es einem ja eiskalt den Rücken runter. Nicht nur, dass niemand mehr die ungarische Notation verwendet (das war für so etwas auch gar nicht vorgesehen und in Python geht es schon gar nicht), <...>
Ich habe eben mal in PEP8 geguckt. Eine Klasse soll mit CapWords benannt werden, hab ich getan. Ok, 'C_' ist scheinbar nicht ganz konform.

Was gibt es gegen die ungarische Notation zu sagen? Wenn ich richtig liege, dann ist es doch die little / big endian Geschichte, die hier reinspielt, oder? Wenn ich Funktionen und Klassen benenne, dann wähle ich die Namen so, daß eine alphabetische Sortierung der Namen klare Sinnzusammenhänge ergibt. Das hilft der Orientierung in fremdem Code enorm und es erzeugt ein konsistentes Bild des Codes. Vor allem ist es beim Debuggen in meinen Augen eine große Hilfe und erspart einem auch etliches an Scrollerei und manchmal auch 'ctrl+f' Sucherei.

Beispiel:
In einem Programm wird Beschleunigung und Geschwindigkeit verarbeitet, dazu werden sie von irgendwo gelesen, irgendwie verarbeitet und auch wieder zurückgeschrieben. Folgende Funktionen sollen definiert sein

Code: Alles auswählen

acc_plausibility_check()
acc_report_critical_value()
acc_value_get()
speed_threshold_check()
speed_threshold_set()
speed_value_get()
speed_value_set()
Auf die Weise ist durch simples Sortieren ein erster klarer Überblick über die Zusammenhänge möglich. Man weiß recht schnell, was alles zur Geschwindigkeitsbehandlung und zur Beschleunigungsbehandlung gehört. Wenn man die Namen so vergeben hätte, wie man normalerweise spricht, sähe es so aus:

Code: Alles auswählen

check_acc_plausibility()
check_speed_threshold()
get_acc_value()
get_speed_value()
report_critical_acc_value()
set_speed_threshold()
set_speed_value()
Natürlich kann es sinnvoll sein, alle get und set Funktionen an einem Ort zu haben, dann kann man es so schreiben, kein Thema. Aber die anderen Beschleunigungs- und Geschwindigkeitsfunctionen sind jetzt auch nicht zusammen aufgeführt.

Selbstverständlich ersetzt das nicht vernünftiges Kommentieren und Dokumentieren. Aber jeder, der schon in Projekten mit Zeitdruck gearbeitet hat wird bestätigen können, daß Kommentare schnell veralten und oder erst gar nicht geschrieben werden. So hat man wenigstens eine kleine Hilfe.

Gruß,

Christoph
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zur Ungarischen Notation: Der Punkt ist, dass es keinen echten Mehrwert bietet. Nicht in statisch typisierten Sprachen, da der Typ meist in der Naehe steht und erst recht nicht in dynamisch typisierten Sprachen, da der Typ nichts mit dem Namen zu tun hat.
Noch dazu ist der Typ in Python weniger wichtig, als wie er sich verhaelt... Klassisches Beispiel ist das "file-like" Protokoll. So, wenn man das jetzt in den Klassennamen oder sonstigen Bezeichnern schreibt .. gute Nacht.

Den Einwand mit dem Sinnzusammenhang verstehe ich absolut nicht: Gehoeren Funktionen zusammen, dann sind sie schon im selben Modul. Tun sie das nicht, sollten sie auch nicht im selben Modul sein (mit der Ausnahme von kleinen Programmen).
Und wenn du jetzt die Namen so waehlen musst(!), dass sie zusammenpassen, hast du das falsche im Fokus. Die Namen sollten in erster Linie etwas aussagen und nicht zuerst die Sortierung bestimmen.
Zu guter letzt, kann nur der Ersteller die Zusammenhaenge kennen, also sollte auch er direkt die Sortierung in der Datei vornehmen und nicht indirekt durch den Namen. Man hat also nicht einmal eine Arbeitsersparnis .. oder man kann sich auf den Ansatz nicht verlassen.

Wenn man dann in Python noch Getter und Setter schreibt macht man sowieso was falsch und sollte sich Properties anschauen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

ChrisGTJ hat geschrieben:Was die Benamsung angeht: Natürlich braucht eine Klasse einen Namen, der was taugt. In diesem Fall ist der Name aber relativ korrekt gewählt, denn es geht um eine Klasse, die einen allgemenien Dialog darstellt und das hinten stehende 'Class' betont das eben noch. Das 'C_' schreibe ich aus Prinzip dazu. Ich gebe Dir aber Recht: In einem normalen Programm hat sowas genau gar nichts verloren.
Was ist denn an deinem Programm so abnormal, dass es so einen Namen braucht? ;-) Die ungarische Notation wird doch auch in C++ schon seit vielen Jahren nicht mehr verwendet, bzw. nur noch sehr sparsam. Das m als Prefix ist noch üblich, häufiger trifft man auch noch auf ein p. Das war es dann. cofi hat ja schon einiges dazu geschrieben, warum sie nicht mehr verwendet wird. Ursprünglich war sie auch gar nicht dazu gedacht, solche schönen Namen wie "mpulZahl" zu erzeugen. Oder noch besser: in die Notation noch irgendwie eigene Typen einzubauen. Besonders spannend wird es immer dann, wenn sich ein Typ ändert und der Name nicht mehr stimmt.

Ganz konkret an deinem Beispiel sieht man doch auch, dass der Kram überflüssig ist. Das C_ deutet auf eine Klasse hin, das "Class" am Ende deutet auf eine Klasse hin und die CamelCase-Schreibweise (auch in C++) deutet auf eine Klasse hin. Dann kann man auch gleich die unnötigen Teile weglassen und einfach genau das hinschreiben was es ist: Dialog.
Das Leben ist wie ein Tennisball.
Benutzeravatar
diesch
User
Beiträge: 80
Registriert: Dienstag 14. April 2009, 13:36
Wohnort: Brandenburg a.d. Havel
Kontaktdaten:

ChrisGTJ hat geschrieben: Auf die Weise ist durch simples Sortieren ein erster klarer Überblick über die Zusammenhänge möglich.
Um Funktionen, Methoden o.ä. alphabetisch sortiert anzuzeigen benötigt man zusätzliche Werkzeuge, die nicht jeder immer griffbereit hat. Ich gruppiere daher meine Funktionen lieber im Quellcode nach Zusammenhang, so dass sich der Quellcode direkt lesen lässt.

Wichtiger als die Frage, nach welchem System Bezeichner benannt werden ist IMHO aber, dass das einmal gewählte System auch konsequent durchgehalten wird und für die Zielgruppe verständlich ist.
cofi hat geschrieben: Wenn man dann in Python noch Getter und Setter schreibt macht man sowieso was falsch und sollte sich Properties anschauen.
Ich verwende Properties nach Möglichkeit nur, wenn der Zugriff darauf sich ähnlich wie der Zugriff auf normale Variablen verhält. Wenn der Zugriff deutlich teurer ist oder nicht-triviale Seiteneffekte hat, verwende ich lieber Getter und Setter.
http://www.florian-diesch.de
Sirius3
User
Beiträge: 17760
Registriert: Sonntag 21. Oktober 2012, 17:20

@diesch: eine Methode die 'get_...' heißt, darf keine nicht-trivialen Seiteneffekte haben. Und wenn eine 'set_...' bzw. 'get_...' Funktion etwas deutlich Komplexeres macht, dann solltest Du Dir überlegen, ob es nicht einen passenderen Namen gibt.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

ChrisGTJ hat geschrieben:Folgende Funktionen sollen definiert sein

Code: Alles auswählen

acc_plausibility_check()
acc_report_critical_value()
acc_value_get()
speed_threshold_check()
speed_threshold_set()
speed_value_get()
speed_value_set()
Auf die Weise ist durch simples Sortieren ein erster klarer Überblick über die Zusammenhänge möglich. Man weiß recht schnell, was alles zur Geschwindigkeitsbehandlung und zur Beschleunigungsbehandlung gehört.
Um Funktionen zusammenzufassen liefert Python ein anderes Mittel: Klassen.

Code: Alles auswählen

speed.check_threshold()
speed.set_threshold()
#...
In C macht man sowas nämlich nur weil es eben keine Klassen gibt.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

ChrisGTJ hat geschrieben:Was gibt es gegen die ungarische Notation zu sagen?
Viel. Sie ist vor allem nicht so verwendet worden, wie Charles Simonyi sich das eigentlich gedacht hat und wie es ursprünglich durchaus erfolgreich eingesetzt wurde. Es geht eben nicht darum, den Datentyp im Namen anzugeben, sondern eher die Bedeutung des Namens im Kontext der Applikation. Auswüchse wie z.B. ein Prefix namens lpsz (long pointer string zero-terminated) kamen erst, nachdem Entwickler außerhalb Simonyis Team die Namensgebung übernommen haben ohne sie richtig verstanden zu haben.

Gerade in Sprachen wie Python mit duck-typing ist die Angabe des Datentyps im Namen üblicherweise völlig sinnfrei.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Sirius3 hat geschrieben:@diesch: eine Methode die 'get_...' heißt, darf keine nicht-trivialen Seiteneffekte haben. Und wenn eine 'set_...' bzw. 'get_...' Funktion etwas deutlich Komplexeres macht, dann solltest Du Dir überlegen, ob es nicht einen passenderen Namen gibt.
Gerade im Zusammenhang mit HTTP APIs hat man ständig irgendwelche 'set_' oder 'get_' Methoden die IO machen, z.b. sowas wie get_tweets. Das ist doch vollkommen legitim.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Hallo,

ich hoffe, es ärgert sich niemand über diese OT Diskussion...

Vorweg, wir diskutieren hier von unterschiedlichen Standpunkten:

Ich bin kein Pythonese, ich bin nicht schlau genug, um die Konzepte dahinter zu verstehen, zumal ich sie nicht wirklich brauche. Ich komme aus der C-Ecke (Steuergeräteprogrammierung), insofern ist die folgende Erkenntnis völlig richtig:
Darii hat geschrieben:Um Funktionen zusammenzufassen liefert Python ein anderes Mittel: Klassen.
<...>
In C macht man sowas nämlich nur weil es eben keine Klassen gibt.
:wink:
diesch hat geschrieben:
ChrisGTJ hat geschrieben: Auf die Weise ist durch simples Sortieren ein erster klarer Überblick über die Zusammenhänge möglich.
Um Funktionen, Methoden o.ä. alphabetisch sortiert anzuzeigen benötigt man zusätzliche Werkzeuge, die nicht jeder immer griffbereit hat. Ich gruppiere daher meine Funktionen lieber im Quellcode nach Zusammenhang, so dass sich der Quellcode direkt lesen lässt.
Ist ein Mißverständnis: Die Sortierung ist natürlich im Quelltext. Durch die von Dir eingeforderte konsequente Namensgebung fällt es leicht, die Sinnzusammenhänge auch in der Position der Funktionen, Klassen und Methoden herzustellen.
Wie Du sagst: Tools stehen nicht immer zur Verfügung, vor allem nicht im LKW auf dem kleinen Laptopbildschirm.
diesch hat geschrieben:Wichtiger als die Frage, nach welchem System Bezeichner benannt werden ist IMHO aber, dass das einmal gewählte System auch konsequent durchgehalten wird und für die Zielgruppe verständlich ist.
Das sollten sich alle Entwickler hinter die Ohren schreiben, setzt aber voraus, daß man ein System definiert hat.

Die Namensgebung ist eh heikel. Wenn ich es nicht schaffe, einen prägnanten Namen für eine Funktion, Klasse oder Variable zu finden, dann ist mir selbst möglicherweise gar nicht klar, wozu die überhaupt da sein soll. Das passiert ja üblicherwise gerade dann, wenn ein Designfehler dazu führt, daß wir workarounds implementieren, weil wir das eigentliche Problem nicht vollständig verstanden oder die Lösung nicht passend ist.
EyDu hat geschrieben:
ChrisGTJ hat geschrieben:Was die Benamsung angeht: Natürlich braucht eine Klasse einen Namen, der was taugt. In diesem Fall ist der Name aber relativ korrekt gewählt, denn es geht um eine Klasse, die einen allgemenien Dialog darstellt und das hinten stehende 'Class' betont das eben noch. Das 'C_' schreibe ich aus Prinzip dazu. Ich gebe Dir aber Recht: In einem normalen Programm hat sowas genau gar nichts verloren.
Was ist denn an deinem Programm so abnormal, dass es so einen Namen braucht? ;-)
Die ungarische Notation wird doch auch in C++ schon seit vielen Jahren nicht mehr verwendet, bzw. nur noch sehr sparsam.
Ich habe den Typen doch gar nicht mit reingeschrieben, insofern verstehe ich den Einwand nicht. Und noch mal: den konkreten Namen 'C_DlgClass' habe ich gewählt, um deutlich zu machen, worum es mir geht. Zumindest das mit 'deutlich' scheint gelungen zu sein... ;)
EyDu hat geschrieben:Besonders spannend wird es immer dann, wenn sich ein Typ ändert und der Name nicht mehr stimmt.
Das hat zwei Seiten:
Wenn die Typinformation nicht unbedingt notwendig ist und trotzdem in einer globalen Schnittstelle verwendet wird, kommt es zu dem im Wikipedia Artikel über die ungarische Notation beschriebenen Problem:

Code: Alles auswählen

Win16: WndProc(HWND hW, WORD wMsg, WORD wParam, LONG lParam)
Win32: WndProc(HWND hW, UINT wMsg, WPARAM wParam, LPARAM lParam)
Das muß man sich natürlich nicht antun.

Auf der anderen Seite gibt es genug Situationen, in denen es auf den Datentypen eben doch ankommt (in nahezu jedem Steuergerät wird es in den Treibern so sein). Und dann bin ich dankbar, wenn ich allein durch die Namensgebung auf Kompatibilitätsprobleme hingewiesen werde, wenn ich auf einem schwachbrüstigen Mikrocontroller mit Bitmasken hantiere (z.B. 32 Bit vs 16 Bit). Den erhöhten Portierungsaufwand nehme ich gern in Kauf, weil es mir ggf. die Hardware eben nicht zerschießt, wenn ich zu doof war, konsequent zu programmieren. Und die Bibliotheken sind in dem Fall inkompatiebel, dann ist es auch egal, ob die Namen nicht passen.

Ich gebe aber gern zu, daß das eher kein Einsatzgebiet für Python ist und für eine API wie die WIN Api ist das natürlich auch keine Option.

Gruß,

Christoph
BlackJack

Beim überdeutlichen `C_DlgClass` hast Du den Datentyp *doch* im Namen, nämlich `Class`, denn das Objekt hat ja den Datentyp `class`¹. Nur falls das nicht klar war: Klassen sind in Python Objekte, also Werte, und wie jeder Wert haben Klassen natürlich auch einen Datentyp. :-)

¹ Je nach Python-Version können Klassen auch den Datentyp `type` haben, aber Datentyp und Klasse sind in Python mittlerweile ja synonym, also ist auch `type` und `class` im Grunde austauschbar.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

BlackJack hat geschrieben:Beim überdeutlichen `C_DlgClass` hast Du den Datentyp *doch* im Namen, nämlich `Class`, denn das Objekt hat ja den Datentyp `class`¹. Nur falls das nicht klar war: Klassen sind in Python Objekte, also Werte, und wie jeder Wert haben Klassen natürlich auch einen Datentyp. :-)
Ok, paßt. Trotzdem lag der Fokus hier nicht auf der Angabe des Typen (aus Unwissenheit natürlich :P), sondern auf der Art (was auch ein Typ ist...).
Antworten