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.
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Moin!

Erstmal der Code:

Code: Alles auswählen

class ClProject():
    
    def __init__(self, pName, pPath):
        self.pName = pName
        self.pPath = pPath

# usf.

class TxMainDialog():
    
    __projExists = False
    __projName = None
    __topLeveLFolder = None 
    __NewProject = None

    def __init__(self):

            self.__topLeveLFolder = self.dialogResult['textFieldShotName']
            self.__projName = self.dialogResult['textFieldProjektName']

            self.__NewProject = ClProject(self.__projName, self.__topLeveLFolder) 
In der letzten Zeile meint der Interpreter einen Type Error zu finden:

"self.__NewProject = ClProject(self.__projName, self.__topLeveLFolder)

__init__() takes exactly 2 arguments (3given)

Also ich seh da zwei Argumente, die ich dem Kontruktor übergebe, keine drei, wo findet der Interpreter die?

Danke fuer Eure Kommentare und Hilfe.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

`self` dürfte das dritte Argument sein dass übergeben wird.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Hier muss irgendwo anders etwas faul sein.

Die __init__() Methode der Klasse ClProject erwartet ja in der Tat genau drei Parameter - inkl. dem self. Da beim Aufruf eine Umwandlung erfolgt, werden bei der Instanzbildung von ClProject tatsächlich drei Parameter übergeben.

Was hier nicht stimmen kann, ist die Meldung, dass nur zwei erwartet werden. Es müssten drei erwartet werden, und die werden ja auch übergeben.
pcos
User
Beiträge: 16
Registriert: Dienstag 3. April 2007, 14:21

Hallo,

schau mal nach, ob

- in dem "usf." (Zeile 8) noch eine __init__ erscheint, die die Version aus Z. 4 überschreibt
- die ganze Klasse ClProject nicht irgendwo überschrieben wird.
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Ja, ich habe da noch eine __init__ ich wollte eben mit einem überladenen Konstruktor arbeiten- geht das in Python nicht?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zumindest überschreibst du mit einer einfachen Definition den ersten. Was für einen Mehrwert erwartest denn davon? IMHO kein gut lesbarer Stil.
Da dürfte jedenfalls dein Problem liegen.
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Überladene Konstruktoren sind super praktisch, aber dann werde ich mich in Python eben davon verabschieden müssen. Danke!!
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Flo668 hat geschrieben:Überladene Konstruktoren sind super praktisch, aber dann werde ich mich in Python eben davon verabschieden müssen. Danke!!
Verabschieden könntest du dich vom Begriff "Konstruktor", denn der trifft hier nicht exakt und wird von den Pythologen eher nicht verwendet.

Was du willst, ist die Überladung der __init__()-Methode und davon musst du dich nicht verabschieden. Du musst nur in der __init__()-Methode auch die __init__()-Methode der vererbenden Klasse explizit aufrufen.

Code: Alles auswählen

class A(object):

    def __init__(self,x):
        self.x = x

class B(A):

    def __init__(self,x,y):
        A.__init__(self,x)
        self.y = y
Flo668
User
Beiträge: 39
Registriert: Mittwoch 23. Juli 2008, 10:41

Ach so. Ich habe das eben gemacht, wie ich es aus anderen OO- Sprachen gewöhnt war. Danke nochmals !
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Flo668 hat geschrieben:Überladene Konstruktoren sind super praktisch
Dann solltest du dir mal Generic Methods ansehen (die es in Python gibt), das setzt noch eins auf Overloading drauf indem nicht nach den Typen der Aufruft dispatched wird sondern quasi nach belibigen Kriterien. Etwa wenn der erste Parameter ein String ist, der ein "ö" enthält. Oder eben quasi beliebige andere Regeln.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

Flo668 hat geschrieben:Ach so. Ich habe das eben gemacht, wie ich es aus anderen OO- Sprachen gewöhnt war. Danke nochmals !
Zumindest in Java, C# und C++ muss man meines Wissens den Konstruktor der Vaterklasse ebenfalls explizit aufrufen.
BlackJack

@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.
barfoos
User
Beiträge: 25
Registriert: Dienstag 29. Juli 2008, 09:46

BlackJack hat geschrieben: 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.
Das ist mir neu. Kannst du das bitte näher erläutern?

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

barfoos hat geschrieben:
BlackJack hat geschrieben: 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.
Das ist mir neu. Kannst du das bitte näher erläutern?
``_name`` steht für: "Implementationsdetail, nicht Teil der API, nicht anfassen, wenn man nicht weiß was man tut". ``__name`` steht für "Name-Mangle, benenne den Namen in _Klassenname_name`` um, um Namenskollisionen zu vermeiden. Solche sind aber ziemlich selten und daher wird sowas auch entsprechend fast nie verwendet.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

In Python gibt es keine privaten Attribute - da ist nicht viel zu erläutern. Es gibt halt keine. Es gibt so eine Art "Pseudoprivatisierung" durch zwei vorangestellte Unterstriche. Auf diese Attribute kann dann nicht "direkt", d.h. nicht über diesen Bezeichner, aber über ein Hintertürchen dann doch zugegriffen werden, so dass auch solche Attribute nicht "privat" sind in dem Sinne, dass ein echter Zugriffsschutz besteht.

Da dem so ist, genügt es folglich auch, nur einen Unterstrich zu verwenden, um so - gemäß Konvention - anzuzeigen, dass dieses Attribut als privat anzusehen ist und man möglichst die Finger davon lassen sollte.

Da sich ein Quelltext mit Bezeichnern, die mit zwei führenden Unterstrichen beginnen, insgesamt eher schlecht liest - vor allem, wenn man dieses Hintertürchen nutzt (siehe dazu das Tutorial) - und es letztlich eh keine echte Privatisierung bringt, kann man es auch gleich lassen und sich auf einen Unterstrich beschränken.
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 ...
Antworten