Módulo 11 - Orientação a objetos: herança
super() e o __init__ da base
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Escrever um __init__ na filha que chama o da base com super().
- Reaproveitar a inicialização da base em vez de repeti-la.
- Acrescentar atributos próprios da filha depois de chamar super.
- Entender por que chamar super primeiro costuma ser o padrão.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: super() e o __init__ da base.
Os objetivos desta aula. Escrever um __init__ na filha que chama o da base com super(). Reaproveitar a inicialização da base em vez de repeti-la. Acrescentar atributos próprios da filha depois de chamar super. Entender por que chamar super primeiro costuma ser o padrão.
Veja o essencial, parte por parte.
O problema que super resolve. super().__init__() chama o construtor da classe base a partir da filha.
Estendendo o construtor com super. Leia o construtor de Cachorro com calma.
A ordem certa e os cuidados. Esquecer de chamar super().__init__(): a filha fica sem os atributos da base e dá erro ao usá-los.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
O problema que super resolve
Na aula anterior a filha não tinha construtor próprio e usava o da base sem esforço. Mas e quando a filha precisa de tudo o que a base guarda mais alguns dados a mais? Um Cachorro é um Animal, então tem nome; mas talvez você queira que o cachorro também tenha uma raça. Se você escrever um __init__ na filha do zero, terá de repetir a linha self.nome = nome, que já existe na base. Repetir é justamente o que a herança veio evitar. A solução é a filha escrever o seu __init__ e, dentro dele, chamar o construtor da base para cuidar da parte que já sabe fazer.
Essa chamada se faz com super().__init__(), passando os argumentos que a base espera. A palavra super se refere à classe base, e __init__ é o construtor dela. É como dizer: base, faça a sua parte da inicialização; depois eu cuido do que é meu. Assim, a lógica de guardar o nome continua morando só na base, e a filha acrescenta apenas o que a diferencia. Se a base mudar como guarda o nome, a filha acompanha de graça, porque delega essa parte para lá.
Estendendo o construtor com super
class Animal:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade
def descricao(self):
return f"{self.nome}, {self.idade} anos"
class Cachorro(Animal):
def __init__(self, nome, idade, raca):
super().__init__(nome, idade) # a base guarda nome e idade
self.raca = raca # a filha guarda o que é dela
rex = Cachorro("Rex", 3, "Vira-lata")
print(rex.descricao()) # Rex, 3 anos
print(rex.raca) # Vira-lataA filha chama super().__init__() e depois acrescenta o atributo raca.
Leia o construtor de Cachorro com calma. Ele recebe nome, idade e raca. A primeira linha, super().__init__(nome, idade), entrega nome e idade para o construtor de Animal, que os guarda em self.nome e self.idade exatamente como faria para qualquer animal. A segunda linha, self.raca = raca, é a contribuição própria da filha. O resultado é um objeto que tem os três atributos, com a inicialização de nome e idade escrita uma vez só, na base. O método descricao, herdado, funciona sem alteração porque encontra nome e idade prontos.
Sem super (repetindo)
- self.nome = nome dentro da filha
- self.idade = idade dentro da filha
- self.raca = raca dentro da filha
- Se a base mudar, a filha fica desatualizada
Com super (reaproveitando)
- super().__init__(nome, idade) delega à base
- A base guarda nome e idade num lugar só
- self.raca = raca é a única linha própria
- Se a base mudar, a filha acompanha sozinha
A ordem certa e os cuidados
Há uma ordem que costuma ser a mais segura: chamar super().__init__() antes de mexer nos atributos próprios da filha. O motivo é prático. Se algum atributo da filha depender de algo que a base prepara, a base precisa ter rodado primeiro. Deixar a chamada ao super no topo do construtor evita esse tipo de surpresa e vira um hábito que raramente falha. Só se afaste dele com um motivo claro, e o curso não precisa desses casos avançados por enquanto.
Um esquecimento clássico é definir o __init__ da filha e não chamar super. Aí o objeto até nasce, mas sem os atributos da base, e o primeiro método herdado que tentar usar self.nome quebra com um erro de atributo. Se você vir esse tipo de falha logo depois de escrever um construtor na filha, a primeira coisa a conferir é se o super().__init__() está lá, com os argumentos certos. Com esse hábito no lugar, estender uma classe base para casos mais específicos vira uma operação rotineira e sem sustos.
Teste rápido
Para que serve super().__init__() dentro do construtor da filha?
Perguntas frequentes
- Sempre preciso chamar super no construtor da filha?
- Sempre que a filha define o seu próprio __init__ e quer os atributos da base, sim. Se a filha não define construtor, ela usa o da base direto e não precisa de super. O cuidado surge quando você escreve um __init__ na filha: aí é preciso chamar super para a base fazer a parte dela.
- O que acontece se eu esquecer o super().__init__()?
- O objeto nasce sem os atributos que a base criaria. Ao usar um método herdado que precise deles, como self.nome, o Python levanta um AttributeError. É um dos erros mais comuns em herança e a primeira coisa a checar quando um método herdado falha.
- Preciso passar argumentos para super().__init__()?
- Você passa os argumentos que o construtor da base espera. Se a base recebe nome e idade, a chamada é super().__init__(nome, idade). Passe exatamente o que a base precisa, na ordem certa. Se a base não recebe nada além de self, basta super().__init__().
- Posso escrever o nome da base em vez de super()?
- É possível chamar Animal.__init__(self, nome) diretamente, mas super() é preferido: funciona melhor com hierarquias e não repete o nome da base, então continua certo se a base mudar de nome. Adote super() como padrão neste curso.
- A filha pode ignorar um argumento e definir um valor fixo?
- Pode. O construtor da filha decide o que passar para a base. Ele pode receber menos argumentos e completar com valores fixos ao chamar super, por exemplo super().__init__(nome, idade=0). Isso é útil quando um tipo específico tem um valor padrão conhecido.
- Por que chamar super antes dos atributos próprios?
- Porque um atributo próprio da filha pode depender de algo que a base prepara. Chamar super primeiro garante que a base já rodou quando a filha começa a definir o que é dela. É um hábito seguro que evita erros sutis de ordem de inicialização.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.