[Fwd: Re: "Typsicherheit" (war: Re: [Python-de] socket und umlaute)]
-----Weitergeleitete Nachricht----- From: Olaf 'Ruebezahl' Radicke <olaf_rad@gmx.de> To: python-liste <python-de@python.net> Subject: Re: "Typsicherheit" (war: Re: [Python-de] socket und umlaute) Date: 23 Nov 2003 01:33:05 +0100 Am Sam, 2003-11-22 um 16.35 schrieb Stefan Schwarzer: [..]
Wenn du "langen verworrenen" Code hast, _schreit_ das nach Vereinfachung/Refaktorierung des Codes, unabhängig davon, ob die Verknüpfung eines Namens mit einem bestimmten Typ möglich ist oder nicht. :-) Letzteres flickt das eigentliche Problem nur sehr notdürftig.
OK. Um mal wieder vom "Allgemeinen" zum "Speziellen" zu kommen: Ich habe eine Klasse "Config" die eine XML-Datei parst und die Werte den anderen Klassen mit get-Methoden zur Verfügung stellt. Jetzt habe ich ja meine Socket-Klasse und die braucht einen Rechnernamen und ein Port. Der Rechnername ist ein str und der Port ein unsigned int. Wo auf dem Weg von der XML-Datei zur Socket-Instanz soll ich den str in ein int umwandeln, so das später noch klar ist ab wo ich es mit was zu tun habe. Wenn mir jetzt später ein fällt, ich will wissen ob eine privilegierte Port-Nummer benutzt wird, muss ich den ganzen Code durchgehen, wo immer der Wert mal durch gereicht wurde, um sicher zu stellen, das diese Code auch das tut was ich von ihm erwarte: SUPERUSERPORTS = 1024 if conf.get_port_numder() <= SUPERUSERPORTS: print "bist du wahnsinnig? Du benutzt Port:", conf.get_port_numder()
Du kannst in Python nicht "aus einem int ein str" machen. Ein Objekt hat immer einen bestimmten Typ (außer vielleicht so pathologischen Fällen wie Zuweisungen an __class__ ;-) ). Meinst du eher "eine Funktion/Methode akzeptiert ein int und gibt ein str zurück"?
Ich will nicht ein und der selben Instanz mal dies, mal das zuweisen dürfen und schon gar nicht Äpfel mit Birnen vergleichen. Ich weiß das einige die Zeiger von C hassen, aber ich könnte mir vorstellen, das man Objekte "TypenStatisch" macht und Zeiger ein führt die auf alles zeigen dürfen nur nicht in's Nirvana. So würde folgender Code immer noch gehen: int_objekt = Klasse_1(int, 4) str_objekt = Klasse_1(str, "4") int_zeiger = Zeiger(int_objekt) str_zeiger = Zeiger(str_objekt) if int_zeiger == str_zeiger: # geht int_objekt == str_objekt # lässt sich erst garnicht starten int_objekt == int(str_objekt) # Carsten ist auch noch ok. Ganz neben bei kann dann auch wieder überladen werden. Und ein if long_double_oblekt_1 > long_duble_oblekt_2: -Bedingung währe dann wahrscheinlich "teurer" als eine if unsigned_int_oblekt_1 > unsigned_int_oblekt_2: -Bedingung.
Wenn ja, musst du die Schnittstellen deiner Module/Klassen/Methoden/Funktionen so entwerfen, dass sie nicht nur irgendwie dein Problem lösen, sondern auch intuitiv - d. h. ohne genaue Kenntnis der inneren Implementierung - benutzbar sind.
Vielleicht könnte man auch einfach ein Interpreter-Schalter "-Typ_Pedantc" machen, der darauf hinweist, wenn man einem Objekt unterschiedlich verwendet.
Für C und C++ sind meine Projekte zu klein (auch personell) als das der Aufwand noch in Relation zum Nutzen stände.
C oder C++ zu verwenden hat m. E. nichts mit der Größe des Projekts zu tun, sondern mit der Art des Projekts. Ich kann mir gut vorstellen, dass auch für viele "große" Projekte Python weitaus besser als C/C++ geeignet ist/wäre.
Ich werde in meinem Code XML in LaTeX parsen. Das ging in C++ rasant schnell. Ich werde sehen was Python dabei für eine Figur macht. Was Größe angeht, hat Zope und Mailman usw. gezeigt was geht. MfG Olaf -- =================================================== "Meine Meinung steht fest. Bitte verwirren sie mich nicht mit Tatsachen!" Unbekannt. =================================================== -- =================================================== "Meine Meinung steht fest. Bitte verwirren sie mich nicht mit Tatsachen!" Unbekannt. =================================================== _______________________________________________ Python-de maillist - Python-de@python.net http://python.net/mailman/listinfo/python-de
Olaf 'Ruebezahl' Radicke wrote:
Jetzt habe ich ja meine Socket-Klasse und die braucht einen Rechnernamen und ein Port. Der Rechnername ist ein str und der Port ein unsigned int. Wo auf dem Weg von der XML-Datei zur Socket-Instanz soll ich den str in ein int umwandeln, so das später noch klar ist ab wo ich es mit was zu tun habe.
Ich würde den Parser erweitern. getBoolean, getInt, getFloat,.... die jeweils den entsprechenden Typ zurückgeben. Da du ja weiß ob dein Wert numerisch oder nicht, drüfte das ja kein Problem sein. conf.getInt("port") <= SUPERUSERPORTS: ... Das hat den vorteil, daß du falsche Werte automatisch in der config Klasse erkennen und aus den defaults übernehmen kannst, z.B. Gruß Daniel -- nihil me cirumdat _______________________________________________ Python-de maillist - Python-de@python.net http://python.net/mailman/listinfo/python-de
Hallo Olaf, On Sun, 2003-11-23 09:08:12 +0100, Olaf 'Ruebezahl' Radicke wrote:
Am Sam, 2003-11-22 um 16.35 schrieb Stefan Schwarzer: [..]
Wenn du "langen verworrenen" Code hast, _schreit_ das nach Vereinfachung/Refaktorierung des Codes, unabhängig davon, ob die Verknüpfung eines Namens mit einem bestimmten Typ möglich ist oder nicht. :-) Letzteres flickt das eigentliche Problem nur sehr notdürftig.
OK. Um mal wieder vom "Allgemeinen" zum "Speziellen" zu kommen: Ich habe eine Klasse "Config" die eine XML-Datei parst und die Werte den anderen Klassen mit get-Methoden zur Verfügung stellt.
Jetzt habe ich ja meine Socket-Klasse und die braucht einen Rechnernamen und ein Port. Der Rechnername ist ein str und der Port ein unsigned int. Wo auf dem Weg von der XML-Datei zur Socket-Instanz soll ich den str in ein int umwandeln, so das später noch klar ist ab wo ich es mit was zu tun habe.
ich würde mir überlegen, was der "natürlichste" Typ (also der, der die abstrakte Sicht am besten wiedergibt) für eine Größe ist, und diesen so früh wie möglich (direkt beim Parsen der XML-Datei) einstellen und dabei bleiben. Manchmal lässt sich die Frage nach dem "natürlichsten" Typ nicht so leicht beantworten, aber in den meisten Fällen wird eine Größe nur mit zwei Typen verwendet: - Ausgabe - alles andere Dann würde ich den für "alles andere" als "natürlichen" Typ ansehen, und für die Ausgabe etwas wie warning = "Port %d is a superuser port" % port # `port` is an int verwenden. Wenn dir das nicht reicht, wäre eine andere - aber deutlich aufwändigere! - Möglichkeit, eine Klasse `Port` zu definieren: class Port: def __init__(self, port): self._port = int(port) def as_string(self): return str(self._port) def as_int(self): return self._port Du solltest dann eine Instanz der Klasse so früh wie möglich erzeugen, also wieder beim Parsen der Konfiguration.
Wenn mir jetzt später ein fällt, ich will wissen ob eine privilegierte Port-Nummer benutzt wird, muss ich den ganzen Code durchgehen, wo immer der Wert mal durch gereicht wurde, um sicher zu stellen, das diese Code auch das tut was ich von ihm erwarte:
Generell solltest du die Möglichkeit, dass es mal das eine oder das andere sein kann, vermeiden, indem du den Typ so früh wie möglich und konsistent festlegst. Wenn du den String oft brauchen solltest, kannst du die Häufigkeit von Missverständnissen verringern, indem du den Typ explizit im Namen unterbringst: port_string = str(port) (Wenn du so einen Namen verwendest und der zugewiesene Wert tatsächlich ein int ist, hast du zugegebenermaßen ein Problem. ;-) )
SUPERUSERPORTS = 1024
if conf.get_port_numder() <= SUPERUSERPORTS: print "bist du wahnsinnig? Du benutzt Port:", conf.get_port_numder()
Du kannst in Python nicht "aus einem int ein str" machen. Ein Objekt hat immer einen bestimmten Typ (außer vielleicht so pathologischen Fällen wie Zuweisungen an __class__ ;-) ). Meinst du eher "eine Funktion/Methode akzeptiert ein int und gibt ein str zurück"?
Ich will nicht ein und der selben Instanz mal dies, mal das zuweisen dürfen und schon gar nicht Äpfel mit Birnen vergleichen.
Dann tu es einfach nicht ;-))
C oder C++ zu verwenden hat m. E. nichts mit der Größe des Projekts zu tun, sondern mit der Art des Projekts. Ich kann mir gut vorstellen, dass auch für viele "große" Projekte Python weitaus besser als C/C++ geeignet ist/wäre.
Ich werde in meinem Code XML in LaTeX parsen. Das ging in C++ rasant schnell. Ich werde sehen was Python dabei für eine Figur macht. Was Größe angeht, hat Zope und Mailman usw. gezeigt was geht.
Empfehlung: 1. alles in Python programmieren; dabei _nicht_ "vorsorglich" optimieren 2. möglichst realistische Anwendungsfälle testen 3. wenn es _wirklich_ zu langsam ist, mit dem Profiler (Modul profile) messen, wo die tatsächlichen Geschwindigkeitsprobleme sind; man kann mit einer Schätzung "aus dem Bauch" manchmal (oder sogar oft) enorm danebenliegen, wodurch man an völlig falschen Stellen "optimieren" würde 4. überlegen, ob das Problem ganz anders gelöst werden kann, so dass der geschwindigkeitskritische Teil gar nicht ausgeführt werden muss; an dieser Stelle fällt einem manchmal ein viel einfacheres Design ein 5. wenn der Aufwand nicht zu groß ist, den Code so ändern, dass die geschwindigkeitskritischen Teile auf der C-Ebene von Python ablaufen (z. B. Verwendung von Listen, Dictionaries, re-Modul etc.) 6. wenn 4. oder 5. zu aufwändig wären oder nicht funktionieren, nach frei verfügbaren Modulen suchen, die geschwindigkeitsoptimiert sind und im wesentlichen das machen, was du willst (z. B. SAX, PyXML, mx.TextTools, NumericPython etc.) 7. wenn 6. nicht geht, aus dem geschwindigkeitskritischen Teil eine C-Erweiterung machen oder Hilfsmittel wie bspw. psyco (http://psyco.sourceforge.net/) verwenden Je mehr Code in C/C++ vorliegt, desto schwieriger wird es sein, die Punkte 4, 5 und 6 anzuwenden. Das spricht paradoxerweise für _weniger_ statt mehr C/C++, um längerfristig die beste Geschwindigkeit zu erreichen bzw. beim "Tunen" flexibel zu bleiben. Eine Frage an die Leser der Mailingliste: Wie sind eure Erfahrungen bzw. was sollte in der obigen Liste ergänzt/geändert werden? Viele Grüße Stefan _______________________________________________ Python-de maillist - Python-de@python.net http://python.net/mailman/listinfo/python-de
participants (3)
-
daniel.poelzleithner
-
Olaf 'Ruebezahl' Radicke
-
Stefan Schwarzer