Seite 1 von 2

Objektvariablen in __init__ werden nicht gesetzt.

Verfasst: Montag 21. September 2009, 19:42
von MikeScript
Hallo.

Mein erstes Anliegen in diesem Forum führt zu einer merkwürdigen Frage: Kann der Konstruktor keine Objektvariablen mit Werten füllen?

Sowohl hier: http://www.python-kurs.eu/klassen.php
als auch hier: http://docs.python.org/reference/datamo ... thod-names
sieht es so aus als ob folgendes gelingen sollte:

Code: Alles auswählen

class Template:

    def __init__(self, tpl):
        '''
        Constructor
        '''
        self._values = {}
        self.__tpl = tpl
        f = open(tpl, "r")
        self.htmlText = f.read()
        f.close
Allerdings bleibt sowohl "htmlText" als auch "__tpl" leer, was ich durch mehrere Versuche dies auszugeben gesehen habe:

Code: Alles auswählen

def __str__(self):
        return self.__tpl
- Aufgerufen mit req.write(str(eine_instanz))

Das ganze läuft unter Py2.5 und ich hoffe mir kann jemand dieses Verhalten erklären.

Gruß,
Zod

Verfasst: Montag 21. September 2009, 19:50
von cofi

Code: Alles auswählen

In [5]: class Template(object):
   ...:     def __init__(self, template):
   ...:         self.values = {}
   ...:         self.tpl = template
   ...:         self.html_text = "abs"
   ...:
   ...:

In [6]: t = Template("xs")

In [7]: t.tpl
Out[7]: 'xs'

In [8]: t.values
Out[8]: {}

In [9]: t.html_text
Out[9]: 'abs'
Wie du siehst funktioniert ``__init__`` (Konstruktor ist falsch, da der in Python 2-stufig ist, ``__new__`` und ``__init__``)

Daneben solltest du mal PEP8 lesen und _einen_ Unterstrich fuer "private" Namen nutzen. Das Konzept gibt es in Python nicht, sondern nur die Konvention den Praefix `_` zu nutzen.

Du solltest mal sagen, wie du denn Exemplare von ``Template`` erzeugst.

Verfasst: Montag 21. September 2009, 20:31
von MikeScript
Ok. Danke für die Coding-Standards.
Ich merke gerade, dass die Ausgabe oder Übersetzung von Python scheinbar gecached wird. Zumindest scheint es so, denn wenn ich den Quelltext ändere, ändert sich nichts an der Ausgabe.

Das ganze läuft auf Apache 2.2.13 mit mod_python für Py2.5. vom Apache aus habe ich Cache-Control so herunter gesetzt, dass nichts gecached wird.

Eine Frage noch hinterher. Es sollen __setattr__ und __getattr__ verwendet werden. Wie erreicht man es, dass trotzdem die Objektvariablen beschrieben werden, sofern sie existieren?

__setattr__ scheint immer Aufgerufen zu werden im gegensatz zu __getattr__ http://www.python.org/doc/2.5.2/ref/att ... ccess.html

Code: Alles auswählen

class Template(object):
    '''
    classdocs
    '''
    
    _values = {}
    _tpl = ""

    def __init__(self, tpl):
        '''
        Constructor
        '''
        self.text = ""  #soll __setattr__ nutzen
        self._values = {}  # soll _values nutzen
        self._tpl = ""  # soll _tpl nutzen
        
        self._tpl = tpl
    
    def __getattr__(self, name):
        return self._values[name]
    
    def __setattr__(self, name, value):
        self._values[name] = value
        
    def __str__(self):
        return str(self._values)

Verfasst: Montag 21. September 2009, 22:00
von cofi
MikeScript hat geschrieben:Das ganze läuft auf Apache 2.2.13 mit mod_python für Py2.5. vom Apache aus habe ich Cache-Control so herunter gesetzt, dass nichts gecached wird.
mod_python hat den denkbar schlechtesten Ansatz um Python auszufuehren. AFAIK sind mod_wsgi und mod_fcgi besser. Am besten erstellst du einen neuen Thread fuer das Problem, damit das auch die Leute lesen, die sich damit auskennen.
MikeScript hat geschrieben:Eine Frage noch hinterher. Es sollen __setattr__ und __getattr__ verwendet werden. Wie erreicht man es, dass trotzdem die Objektvariablen beschrieben werden, sofern sie existieren?

Was meinst du mit Objektvariablen? Die Instanzvariablen? Oder die in deinem values-Dict? IMHO sollte beides immer passieren (in deinem Fall letzteres)
MikeScript hat geschrieben:__setattr__ scheint immer Aufgerufen zu werden im gegensatz zu __getattr__ http://www.python.org/doc/2.5.2/ref/att ... ccess.html
Fuer newstyle-Klassen - erben von ``object`` - gibt es ``__getattribute__``, dort ist der Aufruf garantiert. http://docs.python.org/reference/datamo ... ic-classes

Verfasst: Montag 21. September 2009, 22:19
von hendrikS
cofi hat geschrieben:Daneben solltest du mal PEP8 lesen und _einen_ Unterstrich fuer "private" Namen nutzen. Das Konzept gibt es in Python nicht, sondern nur die Konvention den Praefix `_` zu nutzen.
Warum hat man eigentlich in Py3 mit dieser Katatrophenkonvention nicht mal aufgeräumt? Hat irgendwie so ein halbfertigen Workarround smell. private, public,protected würden der Sprache nicht schaden.

Verfasst: Montag 21. September 2009, 22:39
von cofi
hendrikS hat geschrieben:Warum hat man eigentlich in Py3 mit dieser Katatrophenkonvention nicht mal aufgeräumt? Hat irgendwie so ein halbfertigen Workarround smell. private, public,protected würden der Sprache nicht schaden.
Und welchen Mehrwert haben die Schluesselworte? IMHO ist das nur unnoetiger Clutter und ich finde nicht, dass man sich da an anderen Sprachen orientieren muss, schon gar nicht wenn sie nicht dynamisch sind und ganz anderen Konzepten folgen.

Ohne tiefgreifende Aenderungen am Objektmodell, macht man Versprechungen die man nicht halten kann.

Verfasst: Montag 21. September 2009, 22:40
von BlackJack
@hendrikS: Vielleicht weil es keine Katastrophenkonvention ist, und viele der Meinung sind, dass insbesondere ``private`` der Sprache durchaus schaden kann. Ich habe bisher nur einmal, bei einer Mixin-Klasse, doppelte führende Unterstriche benötigt. Ansonsten reicht mir der dezente Hinweis `_spam` vs. `spam` völlig aus. ``private`` würde ich als Katastrophe ansehen, und das wäre dann ja noch nicht einmal mehr eine Konvention.

Verfasst: Montag 21. September 2009, 22:52
von hendrikS
Die Schlüsselworte stellen sicher, dass Objekte ein eindeutiges Interface haben. Dies ist vermutlich auch die Intension.
Kann mir nicht erklären, was an private schädlich sein soll.
Welchen Mehrwert haben Unterstriche? Keinen, sollte man nicht evtl.die Konvention kennen. Und selbst dann unterbinden sie nichts.
Alle OO Sprachen, die ich außer Python noch kenne (C++,C#,Ruby,Java) haben das. Nur Python macht darum einen Bogen. Ist mir schleierhaft.

Verfasst: Montag 21. September 2009, 22:57
von Hyperion
hendrikS hat geschrieben:Die Schlüsselworte stellen sicher, dass Objekte ein eindeutiges Interface haben.
Inwiefern? Du verbietest doch nur den direkten Zugriff auf ein Attribut... was ist da der Mehrwert?

Das "eindeutig" klingt eher nach starker Typisierung...

Verfasst: Montag 21. September 2009, 23:02
von snafu
Wenn es einem wirklich wichtig ist, dass ein Attribut unveränderbar ist, ließe sich doch auch sowas machen:

Code: Alles auswählen

In [54]: class Foo(object):
   ....:     @property
   ....:     def protected_value(self):
   ....:         return 'you can not change me'
   ....:     
   ....:     

In [55]: foo = Foo()

In [56]: foo.protected_value
Out[56]: 'you can not change me'

In [57]: foo.protected_value = 'but i want to'
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/sebastian/<ipython console> in <module>()

AttributeError: can't set attribute

In [58]: del foo.protected_value
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/sebastian/<ipython console> in <module>()

AttributeError: can't delete attribute

Verfasst: Montag 21. September 2009, 23:07
von snafu
Ich glaube, was hendrikS meint ist, dass z.B. ein `dir()` "geschützte" Attribute nicht ausgeben soll, damit der Nutzer einer Klasse nicht verwirrt ist, sondern nur das angezeigt bekommt, was er verwenden soll.

Verfasst: Montag 21. September 2009, 23:31
von EyDu
hendrikS hat geschrieben:Alle OO Sprachen, die ich außer Python noch kenne (C++,C#,Ruby,Java) haben das. Nur Python macht darum einen Bogen. Ist mir schleierhaft.
Ja, genau. Warum sind nicht gleich alle Sprachen wie Java? ^^

Wenn du nicht erklären kannst, was an private schädlich ist, dann erkläre doch mal die Vorteile. Aber bitte nicht solche lächerlichen Sachen wie "Schutz des Programmierers vor sich selbst", "bessere Übersicht" oder "einfacher für Anfänger". Erstere lassen sich genauso über Konvention regeln und letzteres ist kein wirkliches Argument bei ernsthafter Softwareentwicklung.

Verfasst: Montag 21. September 2009, 23:58
von hendrikS
Den Vorteil und der Sinn des ganzen steht im zweiten Posting zu dem Thema ganz oben. Saubere Schnittstellen sind in der Softwareentwicklung nun mal das A & O. Und eigentlich nicht nur in der Softwareentwicklung.
Sonst würde man ja auch nicht auf die Idee kommen sogar eine jämmerliche PEP Unterstrichkonvention zu definieren.
... die man mit sprachlichen Mitteln in den Skat drücken könnte.

Verfasst: Dienstag 22. September 2009, 00:13
von Darii
hendrikS hat geschrieben:Welchen Mehrwert haben Unterstriche? Keinen, sollte man nicht evtl.die Konvention kennen. Und selbst dann unterbinden sie nichts.
Sie dokumentieren, genauso wie es private auch tut, nur dass man sich bei private anstrengen muss Mist zu bauen. Andererseits erlaubt einem ein offener Zugriff u.U. mehr Flexibilität. Die Frage was jetzt besser ist führt nur zu sinnlosen philosophischen Diskussionen die zu ähnlich ergiebigen Ergebnissen führen, wie die Diskussion dynamische vs. statische Typisierung. Es sind einfach verschiedene Philosophien, man mag sie mögen oder nicht.
Alle OO Sprachen, die ich außer Python noch kenne (C++,C#,Ruby,Java) haben das. Nur Python macht darum einen Bogen. Ist mir schleierhaft.
Dann kennst du kein Smalltalk, um mal ein Gegenbeispiel zu nennen.

Verfasst: Dienstag 22. September 2009, 07:18
von Hyperion
hendrikS hat geschrieben:Den Vorteil und der Sinn des ganzen steht im zweiten Posting zu dem Thema ganz oben.
Meinst Du da Dein eigenes 2. Posting?
hendrikS hat geschrieben: Saubere Schnittstellen sind in der Softwareentwicklung nun mal das A & O.
Dann erkläre doch bitte noch mal, inwiefern ein "private"-Mechanismus Schnittstellen definiert?

Verfasst: Dienstag 22. September 2009, 08:29
von hendrikS
Hyperion hat geschrieben:Dann erkläre doch bitte noch mal, inwiefern ein "private"-Mechanismus Schnittstellen definiert?
Nomen est omen würde ich mal so salopp sagen. Oder gibt es da noch mehr zu erklären?

Verfasst: Dienstag 22. September 2009, 08:35
von Hyperion
hendrikS hat geschrieben:
Hyperion hat geschrieben:Dann erkläre doch bitte noch mal, inwiefern ein "private"-Mechanismus Schnittstellen definiert?
Nomen est omen würde ich mal so salopp sagen. Oder gibt es da noch mehr zu erklären?
Tja, mir will das so nicht in den Kopf, wie "private" helfen soll, ein "eindeutiges Interface" zu schaffen. Wieso ist denn etwas ohne private schlechter? Vielleicht kannst Du da mal ein Beispiel geben?

Verfasst: Dienstag 22. September 2009, 09:37
von cofi
Der einzige Nutzen von Qualifiern ist es, den Zugriff zu dokumentieren, darueber hinaus schafft es nur noch Huerden, fuer den Fall, dass man die Beschraenkung umgehen muss, zB fuer Tests etc.

Das gleiche leistet aber auch eine Konvention. Dass man vom Compiler bei Qualifiern auf die Finger geklopft bekommt, ist ein netter Nebeneffekt, aber das kann man auch mit Tools wie Pylint usw. bewerkstelligen, evtl gibt es auch Interesse solche Warnungen in den Interpreter einzubauen.
Hyperion hat geschrieben:Das "eindeutig" klingt eher nach starker Typisierung...
Statisch, nicht stark ;) Python hat eine starke Typisierung, aber eben auch eine dynamische.
hendrikS hat geschrieben:Welchen Mehrwert haben Unterstriche? Keinen, sollte man nicht evtl.die Konvention kennen. Und selbst dann unterbinden sie nichts.
Und wenn man Schluesselworte benutzt ist das besser? Entschuldige, aber die muss man genauso lernen, fuehrende Leerzeichen sind auch in anderen Sprachen als "reserviert" zu betrachten z.B. C/C++, insofern ist das Argument, dass man die Schluesselworte kennt, nichts wert. Dass man sich mit Idiomen und Konventionen vertraut macht, gehoert eben auch zum Lernen einer Sprache.

Und bitte trennt die Diskussion ab. Das ist wirklich sehr OT.

Verfasst: Dienstag 22. September 2009, 10:04
von lunar
hendrikS hat geschrieben:Die Schlüsselworte stellen sicher, dass Objekte ein eindeutiges Interface haben.
Das ist doch – sei ehrlich – eine einzige große Illusion. Eine Eigenschaft eines Objekts wird nicht dadurch öffentlich, dass ich "public" davor schreibe. Das geschieht erst durch eine vernünftige Dokumentation dieser Eigenschaft. Nur Dokumentation schafft eine wirklich klare und eindeutige Schnittstelle.

Mit Dokumentation aber ist die Zugriffskontrolle ziemlich überflüssig. Man muss nicht extra "private" vor eine undokumentierte Eigenschaft schreiben, um sie als Implementierungsdetail zu kennzeichnen.

Zugriffskontrolle über Schlüsselworte funktioniert doch nur in der Theorie der Sprachdesigner. In der Praxis lässt sich reale, wirksame Zugriffskontrolle mit integrierter Dokumentation und einer unterstützenden Namenskonvention mindestens genauso gut, wenn nicht sogar besser umsetzen.

Edit: In C++ ist "private" sowieso eine Farce. Private Attribute einer Klassen können deren (zur Laufzeit einzig relevante) Binärschnittstelle beeinflussen. Insofern kann man gar nicht so ohne weiteres private Attribute zu einer Klassen hinzufügen, wenn man eine eindeutige Laufzeit-Schnittstelle nach außen hin erhalten will. Das Schlüsselwort ist somit eher kontraproduktiv, weil es etwas unterstellt, was faktisch so gar nicht richtig existiert.

Verfasst: Dienstag 22. September 2009, 14:48
von Leonidas
Darii hat geschrieben:
Alle OO Sprachen, die ich außer Python noch kenne (C++,C#,Ruby,Java) haben das. Nur Python macht darum einen Bogen. Ist mir schleierhaft.
Dann kennst du kein Smalltalk, um mal ein Gegenbeispiel zu nennen.
Oder JavaScript. Oder CLOS. Also kennst du hauptsächlich rote Äpfel, grüne Äpfel und gelbe Äpfel. Keine Birnen und von Bananen gar nicht erst zu sprechen. Daraus dann irgendwelche allgemeinen Aussagen zu machen scheint mir irgendwie zu voreilig.

Außerdem sehe ich nicht wo private Attribute das A & O von Softwareentwicklung sein sollten. Das würde implizieren, dass die Python-Software die existiert irgendwie davon abweicht, aber lustigerweise funktioniert die vorhandene Software durchaus gut.