Wenn Sie aufrufen super()
, um die Version einer Klassenmethode, Instanzmethode oder statischen Methode eines übergeordneten Elements aufzulösen, möchten wir die aktuelle Klasse, in deren Bereich wir uns befinden, als erstes Argument übergeben, um anzugeben, in welchen übergeordneten Bereich wir auflösen möchten und als Ein zweites Argument ist das interessierende Objekt, um anzugeben, auf welches Objekt wir diesen Bereich anwenden möchten.
Betrachten wir eine Klassenhierarchie A
, B
und C
wobei jede Klasse ist die Mutter des einen darauf folgenden, und a
, b
und c
jeweilige Instanzen der einzelnen.
super(B, b)
# resolves to the scope of B's parent i.e. A
# and applies that scope to b, as if b was an instance of A
super(C, c)
# resolves to the scope of C's parent i.e. B
# and applies that scope to c
super(B, c)
# resolves to the scope of B's parent i.e. A
# and applies that scope to c
Verwenden super
mit einer statischen Methode
zB super()
aus der __new__()
Methode heraus verwenden
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return super(A, cls).__new__(cls, *a, **kw)
Erläuterung:
1- obwohl es üblich ist für __new__()
als erstes param einen Verweis auf die anrufenden Klasse zu nehmen, wird es nicht in Python als Class implementiert, sondern ein static. Das heißt, ein Verweis auf eine Klasse muss beim __new__()
direkten Aufruf explizit als erstes Argument übergeben werden:
# if you defined this
class A(object):
def __new__(cls):
pass
# calling this would raise a TypeError due to the missing argument
A.__new__()
# whereas this would be fine
A.__new__(A)
2- Wenn super()
wir aufrufen , um zur übergeordneten Klasse zu gelangen, übergeben wir die untergeordnete Klasse A
als erstes Argument. Dann übergeben wir einen Verweis auf das interessierende Objekt. In diesem Fall ist es die Klassenreferenz, die beim A.__new__(cls)
Aufruf übergeben wurde. In den meisten Fällen handelt es sich auch um einen Verweis auf die untergeordnete Klasse. In einigen Situationen ist dies möglicherweise nicht der Fall, beispielsweise bei Vererbungen mit mehreren Generationen.
super(A, cls)
3- Da es sich in der Regel __new__()
um eine statische Methode handelt, super(A, cls).__new__
wird auch eine statische Methode zurückgegeben, und in diesem Fall müssen alle Argumente explizit angegeben werden, einschließlich des Verweises auf das Objekt von insterest cls
.
super(A, cls).__new__(cls, *a, **kw)
4- das Gleiche tun ohne super
class A(object):
def __new__(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
return object.__new__(cls, *a, **kw)
Verwenden super
mit einer Instanzmethode
zB super()
von innen benutzen__init__()
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
super(A, self).__init__(*a, **kw)
Erläuterung:
1- __init__
ist eine Instanzmethode, dh sie verwendet als erstes Argument einen Verweis auf eine Instanz. Beim direkten Aufruf von der Instanz wird die Referenz implizit übergeben, dh Sie müssen sie nicht angeben:
# you try calling `__init__()` from the class without specifying an instance
# and a TypeError is raised due to the expected but missing reference
A.__init__() # TypeError ...
# you create an instance
a = A()
# you call `__init__()` from that instance and it works
a.__init__()
# you can also call `__init__()` with the class and explicitly pass the instance
A.__init__(a)
2- Wenn wir super()
innerhalb aufrufen, übergeben __init__()
wir die untergeordnete Klasse als erstes Argument und das interessierende Objekt als zweites Argument, das im Allgemeinen auf eine Instanz der untergeordneten Klasse verweist.
super(A, self)
3- Der Aufruf super(A, self)
gibt einen Proxy zurück, der den Bereich auflöst und auf ihn anwendet, self
als wäre er jetzt eine Instanz der übergeordneten Klasse. Nennen wir diesen Proxy s
. Da __init__()
es sich um eine Instanzmethode handelt, übergibt der Aufruf s.__init__(...)
implizit einen Verweis self
als erstes Argument an den übergeordneten __init__()
.
4- Um dasselbe zu tun, ohne dass super
wir einen Verweis auf eine Instanz explizit an die übergeordnete Version von übergeben müssen __init__()
.
class A(object):
def __init__(self, *a, **kw):
# ...
# you make some changes here
# ...
object.__init__(self, *a, **kw)
Verwenden super
mit einer Klassenmethode
class A(object):
@classmethod
def alternate_constructor(cls, *a, **kw):
print "A.alternate_constructor called"
return cls(*a, **kw)
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return super(B, cls).alternate_constructor(*a, **kw)
Erläuterung:
1- Eine Klassenmethode kann direkt von der Klasse aufgerufen werden und verwendet als ersten Parameter einen Verweis auf die Klasse.
# calling directly from the class is fine,
# a reference to the class is passed implicitly
a = A.alternate_constructor()
b = B.alternate_constructor()
2- Wenn Sie super()
innerhalb einer Klassenmethode aufrufen, um sie in die übergeordnete Version aufzulösen, möchten wir die aktuelle untergeordnete Klasse als erstes Argument übergeben, um anzugeben, in welchen übergeordneten Bereich wir auflösen möchten, und das interessierende Objekt als zweites Argument um anzugeben, auf welches Objekt wir diesen Bereich anwenden möchten, der im Allgemeinen auf die untergeordnete Klasse selbst oder eine ihrer Unterklassen verweist.
super(B, cls_or_subcls)
3- Der Anruf wird super(B, cls)
in den Umfang von aufgelöst A
und auf angewendet cls
. Da alternate_constructor()
es sich um eine Klassenmethode handelt, übergibt der Aufruf super(B, cls).alternate_constructor(...)
implizit eine Referenz von cls
als erstes Argument an A
die Version vonalternate_constructor()
super(B, cls).alternate_constructor()
4- super()
Um dasselbe zu tun, ohne es zu verwenden , müssten Sie einen Verweis auf die ungebundene Version von A.alternate_constructor()
(dh die explizite Version der Funktion) erhalten. Einfach das zu tun würde nicht funktionieren:
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
return A.alternate_constructor(cls, *a, **kw)
Dies würde nicht funktionieren, da die A.alternate_constructor()
Methode A
als erstes Argument einen impliziten Verweis auf verwendet . Das hier übergebene cls
Wesen wäre das zweite Argument.
class B(A):
@classmethod
def alternate_constructor(cls, *a, **kw):
# ...
# whatever you want to specialize or override here
# ...
print "B.alternate_constructor called"
# first we get a reference to the unbound
# `A.alternate_constructor` function
unbound_func = A.alternate_constructor.im_func
# now we call it and pass our own `cls` as its first argument
return unbound_func(cls, *a, **kw)