Método de herança e init em Python


98

Eu sou o iniciante do python. Eu não consigo entender herança e __init__().

class Num:
    def __init__(self,num):
        self.n1 = num

class Num2(Num):
    def show(self):
        print self.n1

mynumber = Num2(8)
mynumber.show()

RESULTADO: 8

Isso está bem. Mas eu substituo Num2por

class Num2(Num):
    def __init__(self,num):
        self.n2 = num*2
    def show(self):
        print self.n1,self.n2

RESULTADO: Error. Num2 has no attribute "n1".

Nesse caso, como pode Num2acessar n1?

Respostas:


151

Na primeira situação, Num2está estendendo a classe Nume, como você não está redefinindo o método especial nomeado __init__()em Num2, ele é herdado de Num.

Quando uma classe define um __init__() método, a instanciação da classe invoca automaticamente a instância da classe __init__()recém-criada.

Na segunda situação, como você está redefinindo __init__()em, Num2você precisa chamar explicitamente aquele na superclasse ( Num) se quiser estender seu comportamento.

class Num2(Num):
    def __init__(self,num):
        Num.__init__(self,num)
        self.n2 = num*2

27
Sua citação não é suficiente para explicar por que, ao não definir um __init__método em uma classe derivada, ele é herdado. É porque "se um atributo solicitado não for encontrado na classe, a pesquisa prossegue para procurar na classe base." (doc)
— eyquem

6
Sinto muito ... é basicamente assim que a herança funciona ... se você herda uma classe, obtém o pacote inteiro, então, tudo na superclasse existe na subclasse. Mas, se você redefinir um método, ele é sobrescrito ... isso é o que está em seu código.
— coya

5
@ mario-duarte alguma razão pela qual isso seria melhor do que super(Num2, self).__init__(num)?
— guival

1
Acabei de mudar da solução proposta nesta resposta para usar super, e meu programa agora carrega alguns segundos mais rápido. Não faço ideia do porquê.
— Guimoute

superdeve ser útil ao usar herança múltipla. Para herança única, seus benefícios não são óbvios.
— Johann Bzh



4

Uma mudança simples na classe Num2 como esta:

super().__init__(num) 

Funciona em python3.

class Num:
        def __init__(self,num):
                self.n1 = num

class Num2(Num):
        def __init__(self,num):
                super().__init__(num)
                self.n2 = num*2
        def show(self):
                print (self.n1,self.n2)

mynumber = Num2(8)
mynumber.show()

2
É por isso que adoro stackoverflow. Mesmo que essa não seja a resposta à pergunta, é útil. Às vezes, as respostas que as pessoas postam são as respostas às perguntas que as pessoas deveriam estar fazendo. Obrigado!
— Glen Thompson
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.