In Python 3 kann man super()
anstelle von super(MyClass, self)
verwenden, aber das funktioniert nur in Methoden, die innerhalb der Klasse definiert wurden. Wie in Artikel von Michele Simionato beschrieben, funktioniert das folgende Beispiel nicht:
Dies schlägt fehl, weil super()
nach einer __class__
Zelle sucht, die nicht in definiert ist dieser Fall.
Ist es möglich, diese Zelle manuell zu setzen, nachdem die Funktion definiert wurde, oder ist das unmöglich?
Leider verstehe ich nicht, wie Zellen in diesem Zusammenhang funktionieren (fand dafür nicht viel Dokumentation). Ich hoffe auf etwas wie
%Vor%Natürlich würde ich das nur in einer Situation verwenden, in der die Klassenzuweisung eindeutig / eindeutig ist (der gesamte Prozess des Hinzufügens von Methoden zu einer Klasse wird in meinem Fall automatisiert, so dass es einfach wäre, eine solche Zeile hinzuzufügen).
Aber es ist nützlich für fortgeschrittene Benutzer von Python, das zu verstehen, also werde ich es erklären.
Zellen und Freizeichen sind die Werte, die beim Erstellen eines Abschlusses zugewiesen werden. Zum Beispiel
%Vor% f
gibt eine Schließung basierend auf func
zurück und speichert einen Verweis auf a
. Diese Referenz wird in einer Zelle gespeichert (eigentlich in einer Freevar, aber welche ist die Implementierung). Sie können dies prüfen:
("cells" und "freevars" sind sehr ähnlich. Freevars haben Namen, wo Zellen Indizes haben. Beide sind in func.__closure__
gespeichert, wobei Zellen zuerst kommen. Wir interessieren uns hier nur für freevars
, denn das ist Was __class__
ist.)
Sobald Sie das verstanden haben, können Sie sehen, wie super () tatsächlich funktioniert. Jede Funktion, die einen Aufruf von super
enthält, ist ein Closure mit einem Freizeichen namens __class__
(das auch hinzugefügt wird, wenn Sie sich selbst auf __class__
beziehen):
(Achtung: Hier werden die Dinge böse.)
Diese Zellen sind in func.__closure__
sichtbar, aber sie sind schreibgeschützt. Du kannst es nicht ändern. Die einzige Möglichkeit, dies zu ändern, besteht darin, eine neue Funktion zu erstellen, die mit dem Konstruktor types.FunctionType
ausgeführt wird. Ihre __init__
-Funktion hat jedoch kein __class__
freevar - also müssen wir eins hinzufügen. Das bedeutet, dass wir auch ein neues Code-Objekt erstellen müssen.
Der folgende Code macht das. Ich habe eine Basisklasse B
zu Demonstrationszwecken hinzugefügt. Dieser Code macht einige Annahmen, z. Das __init__
hat noch keine freie Variable namens __class__
.
Hier gibt es einen weiteren Hack: Es scheint keinen Konstruktor für den Zelltyp zu geben. Um dies zu umgehen, wird eine Dummy-Funktion C.dummy
erzeugt, die die von uns benötigte Zellenvariable hat.
Sie können das Wörterbuch der Funktion verwenden.
%Vor% Sie können sogar ein weiteres Attribut member_name
hinzufügen, wenn Sie den Namen des Mitglieds in der Funktion nicht fest codieren wollen.
Vielleicht, aber von dir? In beiden Fällen müssen Sie explizit angeben, um welche Klasse es sich handelt, weil der implizite Weg nicht funktioniert hat. Vielleicht kannst du die Zelle explizit irgendwie setzen, aber dafür gibt es keinen Grund. Übergeben Sie die Parameter einfach explizit.
%Vor%(Es ist besser, wenn Sie die eigentliche Klasse direkt übergeben können, so:
%Vor% Aber wenn du das kannst, könntest du __init__
direkt auf C
setzen, also nimm an, dass du das nicht kannst.
Tags und Links python python-3.x super metaprogramming