Mientras leía sobre el objeto super()
en Python, leí la siguiente statement:
Si se omite el segundo argumento, el objeto super devuelto es independiente
¿Qué significa esto exactamente y cómo uso super()
con un argumento en el código?
Los objetos de función de Python son descriptores , y Python usa el protocolo descriptor para vincular funciones a una instancia. Este proceso produce un método enlazado .
La vinculación es lo que hace que el argumento ‘mágico’ aparezca cuando llama a un método, y lo que hace que un objeto de property
llame automáticamente a los métodos cuando intenta utilizar la propiedad como un atributo en instancias.
super()
con dos argumentos invoca el mismo protocolo descriptor cuando intenta usarlo para buscar métodos en clases primarias; super(Foo, self).bar()
recorrerá las clases primarias de Foo
hasta que se encuentre una bar
atributos, y si ese es un objeto que es un descriptor, estará vinculado a self
. La bar
llamadas llama al método enlazado, que a su vez llama a la función que pasa en el argumento self
como bar(self)
.
Para hacer esto, el objeto super()
almacena tanto la clase (primer argumento) el argumento self
con el que se enlaza, como el tipo del objeto self
como atributos:
>>> class Foo(object): ... def bar(self): ... return 'bar on Foo' ... >>> class Spam(Foo): ... def bar(self): ... return 'bar on Spam' ... >>> spam = Spam() >>> super(Spam, spam) , > >>> super(Spam, spam).__thisclass__ >>> super(Spam, spam).__self_class__ >>> super(Spam, spam).__self__ <__main__.Spam object at 0x107195c10>
Al buscar atributos, se busca el atributo __mro__
atributo __self_class__
, comenzando una posición más allá de la posición de __thisclass__
, y los resultados están vinculados.
super()
con solo un argumento perderá los __self_class__
y __self__
, y aún no puede hacer búsquedas:
>>> super(Spam) , NULL> >>> super(Spam).__self_class__ is None True >>> super(Spam).__self__ is None True >>> super(Spam).bar Traceback (most recent call last): File "", line 1, in AttributeError: 'super' object has no attribute 'bar'
El objeto admite el protocolo descriptor, por lo que puede vincularlo de la misma manera que puede vincular un método:
>>> super(Spam).__get__(spam, Spam) , > >>> super(Spam).__get__(spam, Spam).bar() 'bar on Foo'
Esto significa que puede almacenar un objeto de este tipo en una clase y usarlo para pasar a los métodos principales:
>>> class Eggs(Spam): ... pass ... >>> Eggs.parent = super(Eggs) >>> eggs = Eggs() >>> eggs.parent , > >>> eggs.parent.bar() 'bar on Spam'