Módulo 10 - Orientação a objetos: classes

Atributos de classe e de instância

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Diferenciar atributo de classe de atributo de instância.
  • Definir um atributo de classe direto no corpo da classe.
  • Entender que o atributo de classe é compartilhado por todos os objetos.
  • Reconhecer a armadilha de usar listas como atributo de classe.

Dois tipos de atributo

Até aqui todos os dados eram atributos de instância: cada conta tinha o seu titular e o seu saldo, guardados com self no __init__. Mas há dados que são iguais para todas as contas de um mesmo banco, como o nome da instituição ou uma taxa de manutenção padrão. Repetir esse valor em cada objeto seria desperdício e fonte de erro. Para esses casos existe o atributo de classe, definido direto no corpo da classe, fora do __init__, e compartilhado por todas as instâncias.

class Conta:
    banco = "ValorBank"      # atributo de classe (compartilhado)

    def __init__(self, titular, saldo=0):
        self.titular = titular  # atributo de instancia (proprio)
        self.saldo = saldo

ana = Conta("Ana", 500)
bruno = Conta("Bruno", 30)

print(ana.banco)    # ValorBank
print(bruno.banco)  # ValorBank  (o mesmo para todos)
print(ana.titular)  # Ana  (proprio de cada objeto)

banco é atributo de classe (igual para todos); titular é de instância (por objeto).

No exemplo, banco fica no corpo da classe e vale ValorBank para toda conta criada. Já titular e saldo entram no __init__ com self e mudam de objeto para objeto. Você acessa os dois do mesmo jeito, pelo ponto: ana.banco e ana.titular. A diferença está em onde o dado vive. O de classe é um só, ligado ao molde; o de instância é um por bolo, ligado a cada objeto.

Compartilhado de verdade

Compartilhado significa que existe uma cópia só. Se você mudar o atributo de classe pela própria classe, a mudança aparece em todos os objetos que não têm um valor próprio para aquele nome. É útil para configurar algo uma vez e valer para todas as instâncias. Por outro lado, atribuir pelo objeto (ana.banco = 'Outro') cria um atributo de instância novo só naquele objeto, que passa a esconder o de classe apenas para ele. Entender essa diferença evita confusão.

class Conta:
    taxa = 0.01   # 1% de taxa, igual para todos

    def __init__(self, saldo=0):
        self.saldo = saldo

ana = Conta(1000)
bruno = Conta(2000)

# mudar pela CLASSE afeta todos
Conta.taxa = 0.02
print(ana.taxa, bruno.taxa)  # 0.02 0.02

# mudar pelo OBJETO cria um valor so dele
ana.taxa = 0.05
print(ana.taxa, bruno.taxa)  # 0.05 0.02

Mudar pela classe atinge todos; mudar pelo objeto cria um valor local só dele.

A armadilha da lista compartilhada

Há uma cilada clássica com atributos de classe: usar um valor mutável, como uma lista, direto no corpo da classe. Como existe uma cópia só, todos os objetos passam a dividir a mesma lista. Adicionar um item pensando em um objeto altera a lista de todos, porque é literalmente a mesma. Números e textos não causam esse susto, porque criar um valor novo desconecta o objeto. Com listas e dicionários, o certo é criá-los por objeto, dentro do __init__, com self.

class ContaErrada:
    movimentos = []   # ARMADILHA: lista compartilhada por todos

c1 = ContaErrada()
c2 = ContaErrada()
c1.movimentos.append("deposito 100")
print(c2.movimentos)  # ['deposito 100']  <- vazou para o outro!

class ContaCerta:
    def __init__(self):
        self.movimentos = []   # certo: uma lista por objeto

x = ContaCerta()
y = ContaCerta()
x.movimentos.append("deposito 100")
print(y.movimentos)  # []  (independente)

Lista no corpo da classe vaza entre objetos; no __init__, cada objeto tem a sua.

Em ContaErrada, a lista movimentos é atributo de classe, então c1 e c2 dividem a mesma. O item adicionado em c1 aparece em c2, o que quase nunca é o desejado. Em ContaCerta, movimentos nasce dentro do __init__ com self, então cada objeto ganha a sua própria lista, e as duas não se misturam. A regra prática é direta: dados fixos e iguais para todos podem ser atributo de classe; qualquer coisa que cada objeto precisa modificar por conta própria, principalmente listas e dicionários, deve ser atributo de instância no __init__.

Teste rápido

Por que declarar uma lista como atributo de classe costuma dar problema?

Perguntas frequentes

Onde defino cada tipo de atributo?
O atributo de classe vai direto no corpo da classe, fora de qualquer método, como banco = 'ValorBank'. O atributo de instância vai dentro do __init__, com self, como self.saldo = saldo. O primeiro é um só para todos; o segundo é um por objeto.
Como acesso um atributo de classe?
Pelo objeto (ana.banco) ou pela própria classe (Conta.banco). Os dois funcionam para ler. Para mudar o valor de todos de uma vez, altere pela classe: Conta.banco = 'Outro'. Mudar pelo objeto cria um valor local só dele.
Se eu mudar o atributo pelo objeto, muda para todos?
Não. Atribuir pelo objeto, como ana.taxa = 0.05, cria um atributo de instância só naquele objeto, que passa a esconder o de classe apenas para ele. Os outros continuam com o valor da classe. Para mudar para todos, altere pela classe.
Quando devo preferir atributo de classe?
Quando o valor é igual a todas as instâncias e não muda por objeto: nome do banco, país, uma taxa padrão, um limite fixo. Também serve para um contador de quantos objetos já foram criados. Para tudo que varia por objeto, use atributo de instância.
Por que números e textos de classe não causam a armadilha da lista?
Porque, ao atribuir um número ou texto novo a um objeto, o Python cria um valor novo e desliga aquele objeto do valor da classe. Com listas e dicionários, o append muda o objeto no lugar, sem criar um novo, então a mudança vaza para todos que compartilham a mesma referência.
Posso ter atributo de classe e de instância com o mesmo nome?
Pode, e o Python resolve procurando primeiro no objeto e depois na classe. Se o objeto tem um valor próprio para aquele nome, ele vence; senão, vale o da classe. Isso costuma acontecer quando você atribui pelo objeto um nome que também existe na classe. Evite depender disso para não confundir a leitura.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.