Como invocar o super construtor em Python?
-
25-09-2019 - |
Pergunta
class A:
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
B() # output: hello
Em todas as outras línguas que eu já trabalhou com o super construtor é chamado implicitamente.Como invocá-lo em Python?Eu esperaria super(self)
mas isto não funciona.
Solução
super()
Retorna um objeto parecido com um pai em aulas de novo estilo:
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
B()
Outras dicas
De acordo com as outras respostas, existem várias maneiras de chamar métodos de super classe (incluindo o construtor), no entanto, no Python-3.x, o processo foi simplificado:
Python-2.x
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
Python-3.x
class A(object):
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
super().__init__()
super()
agora é equivalente a super(<containing classname>, self)
conforme os documentos.
Com as aulas de estilo antigo Python 2.x, seria isso:
class A:
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
A.__init__(self)
Uma maneira é chamar o construtor de A e passar self
Como argumento, assim:
class B(A):
def __init__(self):
A.__init__(self)
print "hello"
A vantagem desse estilo é que é muito claro. Ele chama o Inicializador de A. A desvantagem é que ele não lida muito bem com a herança em forma de diamante, já que você pode acabar chamando o Initientar da classe base compartilhada duas vezes.
Outra maneira é usar super (), como outros mostraram. Para uma única elevação, faz basicamente a mesma coisa que permitir que você chame o inicializador do pai.
No entanto, Super () é um pouco mais complicado sob a altura e às vezes pode ser contra-intuitivo em várias situações de herança. No lado positivo, Super () pode ser usado para lidar com a herança em forma de diamante. Se você quiser saber o âmago da questão do que Super () faz, a melhor explicação que encontrei para o modo como Super () funciona aqui (Embora eu não esteja necessariamente endossando as opiniões desse artigo).
Resposta curta
super(DerivedClass, self).__init__()
Resposta longa
O que super()
Faz?
É preciso nome de classe especificado, encontra suas classes base (o python permite a herança múltipla) e procura o método (__init__
neste caso) em cada um deles da esquerda para a direita. Assim que encontrar o método disponível, ele o chamará e terminará a pesquisa.
Como faço para chamar o init de todas as classes base?
Acima funciona se você tiver apenas uma classe base. Mas o Python permite a herança múltipla e você pode garantir que todas as classes base sejam inicializadas corretamente. Para fazer isso, você deve ter cada classe base chamada init:
class Base1:
def __init__():
super(Base1, self).__init__()
class Base2:
def __init__():
super(Base2, self).__init__()
class Derived(Base1, Base2):
def __init__():
super(Derived, self).__init__()
E se eu esquecer de ligar para o init para super?
O construtor (__new__
) é invocado em uma corrente (como em C ++ e Java). Depois que a instância é criada, apenas o inicializador desta instância (__init__
) é chamado, sem nenhuma cadeia implícita para sua superclasse.
Para adicionar apenas um exemplo com parâmetros:
class B(A):
def __init__(self, x, y, z):
A.__init__(self, x, y)
Dada uma classe derivada de B, que requer que as variáveis x, y, z para ser definido, e uma superclasse, o que requer x e y para ser definido, você pode chamar o método estático init da superclasse Um com uma referência para a atual subclasse instância (auto) e, em seguida, a lista dos argumentos.
Eu uso a seguinte fórmula que estende as respostas anteriores:
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(self.__class__, self).__init__()
B()
Dessa forma, você não precisa repetir o nome da classe na chamada para super. Pode ser útil se você estiver codificando um grande número de classes e desejar fazer seu código nos métodos iniciantes independentes do nome da classe.