Conheço duas maneiras de chamar o construtor de uma superclasse a partir de uma classe derivada: super().__init__()
e base.__init__(self)
. Por que a segunda exige que eu forneça explicitamente self
como argumento?
Aqui está um trecho que demonstra a diferença:
class base:
def __init__(self,/):
print("initializing")
class der(base):
def __init__(self):
super().__init__() #no error
base.__init__(self) #no error
base.__init__() #error, self required
obj = der()
A terceira chamada do construtor gera este erro:
File "demo.py", line 11, in <module>
obj = der()
^^^^^
File "demo.py", line 9, in __init__
base.__init__() #error, should be: base.__init__(self)
^^^^^^^^^^^^^^^
TypeError: base.__init__() missing 1 required positional argument: 'self'
Espero base.__init__()
que funcione, pois super().__init__()
não requer um explícito self
.
TL;DR:
super()
é uma instância.der
é uma classe.Para entender isso corretamente, você precisa entender como os métodos de instância funcionam em Python. Ao escrever um método de instância, você precisa incluir
self
como primeiro parâmetro algo como isto:Isso ocorre porque, quando você chama um método de instância, o Python fornece automaticamente a própria instância como o primeiro argumento do método. Estas duas linhas farão a mesma coisa:
A única diferença é que a primeira linha chama
bar
de uma instância e a segunda chamabar
de uma classe .No seu exemplo,
base
é uma classe (o equivalente aFoo
) em vez de uma instância (o equivalente ax
). Portanto, se você quiser chamar obase
construtor, precisará fornecer manualmenteself
- Python não fará isso por você.A
super
versão não precisa disso porquesuper
não é a classebase
- é um proxy para a instânciaself
que finge ser do tipoder
em vez do tipobase
. Isso significa que aindasuper()
é uma instância , não uma classe, entãosuper().__init__()
será fornecido automaticamenteself
como parâmetro parabase.__init__
e você não precisa fazer isso manualmente.