Warum wird __init__ nicht nach __new__ SOMETIMES aufgerufen?

8

Lass mich damit beginnen, es ist keine Wiederholung von Warum wird __init__ nicht aufgerufen, wenn __new__ ohne Argumente aufgerufen . Ich habe versucht, einige Beispielcode für __new__ und __init__ sorgfältig zu konstruieren, die keine Erklärung finden kann, die ich finden kann.

Die grundlegenden Parameter:

  • Es gibt eine Basisklasse namens NotMine, da sie aus einer anderen Bibliothek stammt (ich werde das am Ende veröffentlichen, hier nicht wichtig)
  • Diese Klasse hat eine __init__ -Methode, die wiederum eine _parse -Methode
  • aufruft
  • Ich muss die Methode _parse in Unterklassen
  • überschreiben
  • welche Unterklasse ich erstelle, ist bis zum Aufruf
  • nicht bekannt
  • Ich weiß, dass es Factory-Design-Methoden gibt, aber ich kann sie hier nicht verwenden (Mehr am Ende)
  • Ich habe versucht, super vorsichtig zu verwenden, um die Probleme zu vermeiden Python-Protokollierung: Warum wird __init__ zweimal aufgerufen?
  • Ich weiß, das ist auch "irgendwie" eine Möglichkeit von AbstractBaseMehtod, aber das hat nicht geholfen

Wie auch immer, __init__ sollte nach __new__ aufgerufen werden und für jede Erklärung, warum einige Beispiele unten nicht funktionieren, scheint es mir möglich zu sein, auf andere Fälle hinzuweisen, die funktionieren und die Erklärung ausschließen.

> %Vor%

Wenn Sie den Code ausführen, können Sie sehen, dass bei jedem Aufruf von __new__ angezeigt wird, "welche Tür" durch welchen Typ durchgeht. Ich kann die gleiche "Tür" mit dem gleichen "Typ" -Objekt verlassen und __init__ in einem Fall aufgerufen haben und nicht den anderen. Ich habe mir den mro der "Calling" -Klasse angeschaut und das bietet keinen Einblick, da ich diese Klasse (oder eine Unterklasse wie in CCC) aufrufen kann und __init__ called.

Ende Anmerkungen: Die NotMine -Bibliothek, die ich benutze, ist die Genshi MarkupTemplate und der Grund dafür, dass keine Factory-Design-Methode verwendet wird, ist, dass ihr TemplateLoader ein benötigt defaultClass zu konstruieren. Ich weiß es nicht, bis ich mit dem Parsen anfange, was ich in __new__ mache. Es gibt eine Menge cooler Voodoo-Magie, die Genshi-Loader und Templates machen, die sich lohnen.

Ich kann eine unveränderte Instanz ihres Loaders ausführen und derzeit funktioniert alles, solange ich NUR die ABC-Klasse (abstrakte Sortierreihenfolge) als Standard übergebe. Die Dinge funktionieren gut, aber dieses unerklärliche Verhalten ist später ein fast sicherer Fehler.

UPDATE: Ignacio, die Topline-Frage genagelt, wenn das zurückgegebene Objekt keine "Instanz von" cls ist, dann wird __init__ nicht aufgerufen. Ich finde, dass das Aufrufen des "Konstruktors" (zB AA(args..) falsch ist, da es __new__ wieder aufruft und Sie wieder da sind, wo Sie angefangen haben. Sie könnten ein Argument ändern, um einen anderen Pfad zu wählen. co_de% zweimal statt unendlich Eine Arbeitslösung besteht darin, ABC.__new__ oben als:

zu bearbeiten %Vor%

Beachten Sie die letzten Zeilen. Kein Aufruf von class ABC , wenn es sich um eine "andere" Klasse handelt, macht für mich keinen Sinn, BESONDERS wenn die "different" -Klasse noch eine Unterklasse der Klasse ist, die __init__ aufruft. Ich mag den obigen Schnitt nicht, aber am wenigsten verstehe ich jetzt die Regeln.

    
Phil Cooper 20.02.2012, 19:22
quelle

2 Antworten

8

Aus der Dokumentation :

  

Wenn __new__() keine Instanz von cls zurückgibt, wird die __init__() -Methode der neuen Instanz nicht aufgerufen.

Dies ist, damit __new__() eine neue Instanz einer anderen Klasse zurückgibt , die stattdessen ihr eigenes __init__() hat. Sie müssen feststellen, ob Sie ein neues cls erstellen, und andernfalls den entsprechenden Konstruktor aufrufen.

    
Ignacio Vazquez-Abrams 20.02.2012, 19:28
quelle
-1

Nur meine zwei Cent hier, aber warum benutzt du nicht die Python-Ente-Eingabe, um Genshi etwas zu geben, das sich wie eine Klasse verhält?

Ich habe einen kurzen Blick auf Genshi Quellcode geworfen und die einzigen Anforderungen, die ich habe sah auf dem 'class' Parameter für den TemplateLoader ist, dass es mit den gegebenen Argumenten aufrufbar ist.

Ich denke, es wäre einfacher, eine Klasse mit einer Factory-Funktion zu verspotten, die die tatsächlich erstellte Instanz zurückgibt.

    
rotoglup 20.02.2012 22:09
quelle

Tags und Links