Compreendendo Variáveis de Classe e de Instância em Python: Mecanismos de Acesso

Entender como o Python acessa e gerencia variáveis associadas a classes e objetos é fundamental. Este guia detalha o processo de busca de atributos e os princípios por trás do compartilhamento de dados.

Conceitos Fundamentais: Classe vs. Instância

Uma classe define o molde, o projeto que estabelece a estrutura e comportamentos. Uma instância é um objeto concreto criado a partir desse molde.

  • Variável de Classe: Definida no corpo da classe, fora de qualquer método. Pertence à classe e é compartilhada por todas as suas instâncias. Geralmente usada para constantes ou dados comuns a todos os objetos.
  • Variável de Instância: Normalmente definida dentro do método __init__ usando self. Cada instância mantém sua própria cópia independente. Serve para armazenar dados únicos de cada objeto.

Sequência de Busca de Atributos

Ao acessar objeto.atributo, o inteprretador segue uma ordem específica, conhecida como cadeia de resolução de métodos (MRO) simplificada para atributos.

Acessando um Atributo

  1. Busca na Instância: Verifica primeiro o dicionário de atributos da instância (objeto.__dict__).
  2. Busca na Classe: Se não encontrado, busca no dicionário da classe (Classe.__dict__).
  3. Busca nas Classes Mãe: Continua subindo na hierarquia de herança até encontrar ou lançar um AttributeError.

Atribuindo um Valor (objeto.atributo = valor)

O comportamento depende da intenção:

Cenário 1: Criar/Modificar uma Variável de Instância (Ação mais comum)

def __init__(self, modelo):
    self.modelo = modelo  # Variável de instancia

carro_a = Automovel("Sedan") carro_b = Automovel("SUV")

Ambos acessam a variável de classe inicialmente

print(carro_a.rodas) # Saída: 4 print(carro_b.rodas) # Saída: 4

Atribuição via instância

carro_a.rodas = 6 # Cria uma variável de INSTÂNCIA 'rodas' em carro_a

print(carro_a.rodas) # Saída: 6 (encontra na instância) print(carro_b.rodas) # Saída: 4 (busca na classe) print(Automovel.rodas) # Saída: 4 (acesso direto à classe)

print(carro_a.dict) # {'modelo': 'Sedan', 'rodas': 6}


</div>**Explicação:** A operação `carro_a.rodas = 6` **não** altera a variável de classe. Em vez disso, ela **cria uma nova variável** com o mesmo nome (`rodas`) no espaço de nomes da instância `carro_a`. Esse fenômeno é chamado de **sombreamento de atributo**.

**Cenário 2: Modificar a Variável de Classe através da Instância** (Geralmente não recomendado)

<div class="code-example">```
# Continuando o exemplo anterior
carro_a.__class__.rodas = 8  # Acessa a classe via __class__ e modifica

print(carro_a.rodas)  # Saída: 6 (sua própria variável de instância)
print(carro_b.rodas)  # Saída: 8 (buscou na classe, que agora vale 8)
print(Automovel.rodas)  # Saída: 8

Princípio de Implementação: Dicionários e Espaços de Nomes

Internamente, o Python armazena atributos em estruturas de dicionário.

  • Espaço de Nomes da Instância: É representado pelo objeto.__dict__. Quando você escreve self.cor = "vermelho", está fazendo self.__dict__['cor'] = "vermelho".
  • Espaço de Nomes da Classe: É representado por Classe.__dict__, contendo variáveis de classe, métodos e outros atributos definidos no nível da classe.

Um espaço de nomes (namespace) é um mapeamento de nomes para objetos. A sequência de busca por atributos segue esta ordem: Espaço da Instância → Espaço da Classe → Espaço das Classses Mãe.

Armadilhas Comuns e Boas Práticas

Atrapalhe Clássica: Objetos Mutáveis como Variáveis de Classe

produto_1 = Inventario() produto_2 = Inventario()

produto_1.itens.append("Parafuso")

Ambas as instâncias e a classe veem a alteração

print(produto_1.itens) # ['Parafuso'] print(produto_2.itens) # ['Parafuso'] print(Inventario.itens) # ['Parafuso']


</div>**Solução:** Para dados mutáveis específicos de cada instância, inicialize-os no `__init__`.

<div class="code-example">```
class InventarioCorreto:
    def __init__(self):
        self.itens = []  # Cada instância recebe sua própria lista

item_1 = InventarioCorreto()
item_2 = InventarioCorreto()
item_1.itens.append("Arruela")
print(item_1.itens)  # ['Arruela']
print(item_2.itens)  # []

  1. Separação Clara: Defina variáveis de classe no topo da definição da classe e variáveis de instância dentro do __init__.
  2. Modificação Intencional: Use Classe.atributo para alterar variáveis de classe. Evite instância.atributo para esse propósito.
  3. Cautela com Dados Compartilhados: Prefira inicializar estruturas mutáveis como listas ou dicionários dentro de __init__, a menos que o compartilhamento seja o objetivo.

Tags: Python Orientação a Objetos variáveis de classe variáveis de instância __dict__

Publicado em 6-27 02:26