Konstruktor bekommt 2 Argumente, der Interpreter findet drei

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.
BlackJack

Die doppelten Unterstriche sind dazu gedacht Namenskollisionen zu verhindern, nicht um den Zugriff unmöglich zu machen. An die Attribute kommt man nämlich auch weiterhin von aussen dran, es wird ja nur der Name verändert:

Code: Alles auswählen

In [32]: class A(object):
   ....:     def __init__(self):
   ....:         self.__spam = 42
   ....:

In [33]: a = A()

In [34]: a._A__spam
Out[34]: 42
Das ist nützlich wenn man mit tiefen Vererbungshierarchien oder Mehrfachvererbung arbeitet. Tiefe Vererbungshierarchien sind in Python eher unüblich -- ich habe das bisher auch nur bei MixIn-Klassen verwendet. Und die verwende ich auch nicht oft, weil Mehrfachvererbung halt auch so seine Tücken hat.

Per Konvention bedeutet *ein* führender Unterstrich "Achtung, Implementierungsdetail! Verwenden auf eigene Gefahr!".
barfoos
User
Beiträge: 25
Registriert: Dienstag 29. Juli 2008, 09:46

BlackJack hat geschrieben:h auch nicht oft, weil Mehrfachvererbung halt auch so seine Tücken hat.

Per Konvention bedeutet *ein* führender Unterstrich "Achtung, Implementierungsdetail! Verwenden auf eigene Gefahr!".
OK, danke für die Aufklärung. Mit war klar, dass der Doppelunterstrich eine Namensersetzung macht. Mir war nur nicht klar, dass man den per Konvention trotzdem lieber den einfachen Unterstrich nimmt.

Mein Problem ist wahrscheinlich, dass ich aus der Java-Welt komme. Gerade der Fakt, dass ich zur Compilezeit kaum erkennen kann, welche Attribute durch Vererbung/Mehrfachvererbung bereits existieren, hat mich dazu bewogen recht üppig von den doppelten Unterstrichen gebraucht zu machen, um nicht versehentlich ein Attribut doppelt zu belegen.

Frisst der Doppelstrich denn viel Rechenleistung, oder wird das beim Kompilieren geregelt?

Danke und gruß
barfoos
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

barfoos hat geschrieben:Frisst der Doppelstrich denn viel Rechenleistung, oder wird das beim Kompilieren geregelt?
Nein und nein. Es ist wird einfach die Methode anders benannt, das ist alles. Sowas kannst du dir auch selbst schreiben, wenn der Interpreter das nicht bereits machen würde.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Fabian Kochem
User
Beiträge: 36
Registriert: Mittwoch 5. April 2006, 14:11
Wohnort: Köln

barfoos hat geschrieben: Mein Problem ist wahrscheinlich, dass ich aus der Java-Welt komme. Gerade der Fakt, dass ich zur Compilezeit kaum erkennen kann, welche Attribute durch Vererbung/Mehrfachvererbung bereits existieren, hat mich dazu bewogen recht üppig von den doppelten Unterstrichen gebraucht zu machen, um nicht versehentlich ein Attribut doppelt zu belegen.
Was meinst du mit Compilezeit?
Während des Programmierens musst du halt selbst wissen, welche Klasse von wo vererbt. Schließlich hast du den Code ja auch geschrieben, oder?
Falls du während der Laufzeit meintest, hier ein kleiner Tip:

Code: Alles auswählen

>>> class Foobar:
...     foo = 1.0
...
>>> class Barfoo(Foobar):
...     bar = 2.0
...
>>> f = Foobar()
>>> dir(f)
['__doc__', '__module__', 'foo']
>>> b = Barfoo()
>>> dir(b)
['__doc__', '__module__', 'bar', 'foo']
>>>
lunar

Fabian Kochem hat geschrieben:
barfoos hat geschrieben: Mein Problem ist wahrscheinlich, dass ich aus der Java-Welt komme. Gerade der Fakt, dass ich zur Compilezeit kaum erkennen kann, welche Attribute durch Vererbung/Mehrfachvererbung bereits existieren, hat mich dazu bewogen recht üppig von den doppelten Unterstrichen gebraucht zu machen, um nicht versehentlich ein Attribut doppelt zu belegen.
Was meinst du mit Compilezeit?
Äh, mal naiv geraten: Die Zeit, in der ein Quellcode kompiliert wird? Jaja, iIch weiß, ist irgendwie weit hergeholt, aber vielleicht hab ich ja heute Glück im Raten ...
pcos
User
Beiträge: 16
Registriert: Dienstag 3. April 2007, 14:21

Das ist jetzt ein wenig off-topic:

Ich schaue mir meinen Beitrag oben an und wunder mich, wieso da ein Smiley steht, der Satz völlig verdreht ist und eine Klammer fehlt. War ich da besoffen? Nach einiger Zeit hat's mir gedämmert: Das Zeichen "8" und darauffolgendes ")" werden als Shortcut für den Smiley interpretiert.

Und das ist einem Forum zu einer Sprache, die auf magic features pfeift! :wink:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

pcos hat geschrieben: Und das ist einem Forum zu einer Sprache, die auf magic features pfeift! :wink:
Das Forum ist ja auch kein Python, sondern diese andre Sprache mit dem P ... dieses schreckliche .. ihr wisst schon ;)
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

BlackJack hat geschrieben:@Flo668: Ich möchte noch einmal nachfragen, was denn so superpraktisch am überladen ist? In den meisten Fällen, die ich zum Beispiel aus Java kenne, kann man das in Python mit "default" Argumenten lösen.

Und da Du andere OO-Sprachen erwähnst: In Python gibt es kein "private" und Deine vielen doppelten Unterstriche riechen nach Missbrauch dieses Mechanismus. Wenn Du "private" Attribute haben möchtest, reicht ein einzelner führender Unterstrich um dies zu kennzeichnen.
"Praktisch" ist Geschmackssache. In meinem Fall war es so, dass es zwei Optionen gibt. Einerseits das Öffnen einer bestehenden Projektdatei und andererseits das neu Anlegen einer Projektdatei und darauffolgendes Öffnen.

Also bin ich her gegnagen und habe je nach Fall entschieden, welcher "Konstruktor" für diese Projektdatei eben verwendet werden soll.
Ich finde sowas praktisch, andere vielleicht nicht.

Was das mit den Strichen angeht, so habe ich nur das getan, was mir in meinem Python Lehrbuch erklärt wurde. Dort stand, dass der doppelte Unterstrich privaten Klassenattributen entsprechen würde.
Warum man bei der Konstruktion von Python auf dieses Feature dann doch verzichtet hat, wüsste ich mal gerne. Ich erinnere mich da an Informatikvorlesungen wo lang, breit und ausführlich dieses Design als eines der Herausstellungsmerkmale Objektorientierter Sprechen zelebriert wurde.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Flo668 hat geschrieben:Was das mit den Strichen angeht, so habe ich nur das getan, was mir in meinem Python Lehrbuch erklärt wurde. Dort stand, dass der doppelte Unterstrich privaten Klassenattributen entsprechen würde.
Das Buch von Galileo Computing etwa? Das Buch ist eigentlich "Java ist auch eine Insel" nur mit Python-Syntax. Nicht empfehlenswert.
Flo668 hat geschrieben:Warum man bei der Konstruktion von Python auf dieses Feature dann doch verzichtet hat, wüsste ich mal gerne. Ich erinnere mich da an Informatikvorlesungen wo lang, breit und ausführlich dieses Design als eines der Herausstellungsmerkmale Objektorientierter Sprechen zelebriert wurde.
Dieses Feature hast du in Python auch, indem du einen `_` vor die Variable setzt, womit du definierst, dass es nicht zum öffentlichen Interface der Klasse gehört. Letztendlich ist das so wie in Java auch, nur dass du dort die Reflection-API brauchst um dich an private Attribute ranzumachen, wärend du in Python einen ``_`` schreibst. Und es ist manchmal doch nützlich private Attribute zu modifizieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Welches Python-Buch schreibt sowas, wenn ich fragen darf?
  • In Python gibt es keine privaten Variablen oder Methoden.
  • Konvention: Attribute, auf die nicht von aussen zugegriffen werden sollte, beginnen mit einem Unterstrich: _foo.
  • Um Namenskonflikte zu vermeiden: Namen der Form __foo werden durch _klassenname__foo ersetzt:

Code: Alles auswählen

class Spam:
    __eggs = 3

Code: Alles auswählen

>>> dir(Spam)
>>> ['_Spam__eggs', '__doc__', '__module__']
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Leonidas hat geschrieben: Das Buch von Galileo Computing etwa? Das Buch ist eigentlich "Java ist auch eine Insel" nur mit Python-Syntax. Nicht empfehlenswert.
Nein Addison Wesley, "Peter Walerowski: Python- Grundlagen und Praxis" auf S. 116


Um nun zu verhindern, dass ein direkter Zugriff auf das Attribut (...) stattfindet, kann dies nach außen hin abgeschottet werden. Dies erreicht man durch das Voranstellen von zwei Unterstrichen (__) vor den Attributsnamen.(...). Ein solches Attribut wird auch als privat bezeichnet.


Ich kann das Buch auch aus diversen anderen Gründen nicht weiter empfehlen.
BlackJack

@Flo668: Wenn ich das richtig verstanden habe, kann man das sehr einfach mit einem Argument lösen:

Code: Alles auswählen

def Project(object):
    def __init__(self, filename, create_new=False):
        pass
Oder eben `True` als Vorbelegung.

Wenn es mehrere alternative "Konstruktoren" gibt, die sich nicht so einfach durch Default-Argumente "auswählen" lassen, bieten sich `staticmethod`\s bzw. `classmethod`\s an. Beispiel, ein Objekt das man laden und speichern kann, wo `load()` sozusagen ein alternativer "Konstruktor" ist:

Code: Alles auswählen

class Parrot(object):
    def __init__(self, spam, eggs=42):
        self.spam = spam
        self.eggs = eggs
    
    @classmethod
    def load(cls, filename):
        # Daten laden.
        return cls(spam, eggs)
    
    def save(self, filename):
        # Daten speichern.
lunar

Leonidas hat geschrieben:Letztendlich ist das so wie in Java auch, nur dass du dort die Reflection-API brauchst um dich an private Attribute ranzumachen.
Was ja per se auch nicht verwerflich ist, immerhin möchte man ja vielleicht auch mal private Methoden unittesten. Wohl aus diesem Grund funktioniert der Weg über Reflection meines Wissens auch in .NET.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lunar hat geschrieben:
Leonidas hat geschrieben:Letztendlich ist das so wie in Java auch, nur dass du dort die Reflection-API brauchst um dich an private Attribute ranzumachen.
Was ja per se auch nicht verwerflich ist, immerhin möchte man ja vielleicht auch mal private Methoden unittesten. Wohl aus diesem Grund funktioniert der Weg über Reflection meines Wissens auch in .NET.
Ja, sicher. Wirft dem Programmierer aber IMHO mehr Steine in den Weg als nötig. Im Vergleich scheint "Nutze die Reflection-API" vs. "Schreibe ein ``_`` vor den Namen" als eine eher umständliche Art das selbe zu erreichen aus. Was ich damit sagen will: beide Methoden sing gleichwertig, jedoch ist die Methode einen Bodenstrich vor den Namen zu schrieben schlichtweg unkomplizierter.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Irgendwie habe ich da ein Händchen fuer...nur verstehe ich es einfach nicht:

Code: Alles auswählen

    def _getText(nodelist):
        # usf.

     def _printData(self):
        for ce in self._list:
            print 'NEUES ELEMENT \n'
            n = ce.uri
            print self._getText(n)  

Und die Fehlermeldung:

print self._getText(n)
TypeError: _getText() takes exactly 1 argument (2 given)

...ich meine auf beiden Seiten nur eins zu zählen. Merkwürdig.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Wenn du einen solchen Aufruf machst:

Code: Alles auswählen

self._getText(n)
wird dieser intern so verarbeitet

Code: Alles auswählen

MeineKlasse._getText(self, n)
Ganz einfach ;)

Deswegen müssen Methoden einer Klasse auch als erstes ein Objekt für die Klasseninstanz haben. Sonst hättest du keine Möglichkeit darauf zuzugreifen.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

private/protected sind nirgendswo richtig abgeschottet (von PHP vielleicht abgsehen). In C++ kannst du sie dir wegcasten, in Java kann das die Reflection API und in .NET kommst du auch mit Reflection weg wenn der Code nicht mit einer Security Policy abgeschottet wurde (was afair Silverlight macht).

__ ist private, nur das viele glauben private == protected.
TUFKAB – the user formerly known as blackbird
Antworten