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.

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-lata

A 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.