Função vars() em Python: Guia Prático de Introspecção

A função vars() em Python é uma ferramenta de inrtospecção que permite acessar o estado interno de objetos através de seus atributos. Este guia explora como utilizá-la de forma eficaz.

Fundamentos da função vars()

Como função nativa do Python, vars() retorna o atributo __dict__ de um objeto, que nada mais é do que um dicionário contendo as propriedades graváveis desse objeto. Este mecanismo funciona com módulos, classes e instâncias.

Há duas formas de invocá-la:

  • Sem argumentos: devolve o dicionário do escopo local atual, com comportamento idêntico a locals().
  • Com argumento: devolve o __dict__ do objeto informado.

A assinatura da função é:

vars([objeto])

Exemplos práticos

1. Chamada sem argumentos: inspecionando o escopo local

Quando chamada dentro de uma função, vars() retorna as variáveis daquele escopo:

def processar_dados():
    contador = 42
    mensagem = "processando"
    estado = vars()
    print(estado)

processar_dados()
# Saída aproximada: {'contador': 42, 'mensagem': 'processando', ...}

No nível do módulo, retorna o namespace global:

valor_a = 100
valor_b = "teste"
print(vars()["valor_a"])  # Saída: 100

2. Inspecionando atributos de objetos

Módulos: ao passar um módulo, você obtém todos os símbolos definidos nele:

import os
simbolos_os = vars(os)
print("sep" in simbolos_os)  # Saída: True

Classes: a função revela variáveis de classe, métodos e metadados:

class Configuracao:
    padrao = "producao"
    
    def __init__(self):
        self.ambiente = "desenvolvimento"

info_classe = vars(Configuracao)
print(list(info_classe.keys()))
# Saída aproximada: ['__module__', 'padrao', '__init__', ...]

Instâncias: expõem os atributos de instância armazenados:

class Produto:
    def __init__(self, codigo, preco):
        self.codigo = codigo
        self.preco = preco

item = Produto("ABC123", 59.90)
atributos = vars(item)
print(atributos)
# Saída: {'codigo': 'ABC123', 'preco': 59.9}

3. Manipulação dinâmica de atributos

Como vars() retorna uma referência direta ao dicionário interno, alterações nesse dicionário afetam o objeto original:

class Funcionario:
    def __init__(self, nome, cargo):
        self.nome = nome
        self.cargo = cargo

empregado = Funcionario("Carlos", "Desenvolvedor")
dados = vars(empregado)

# Atualizando um atributo existente
dados["cargo"] = "Tech Lead"

# Criando um novo atributo dinamicamente
dados["salario"] = 8500.00

print(vars(empregado))
# Saída: {'nome': 'Carlos', 'cargo': 'Tech Lead', 'salario': 8500.0}

4. Utilização em debug

Durante sessões de depuração, vars() oferece uma visão rápida do estado de objetos complexos:

# Em um ponto de interrupção durante debug
estado_objeto = vars(objeto_complexo)
for chave, valor in estado_objeto.items():
    print(f"{chave}: {valor}")

Restrições e cuidados importantes

1. Necessidade de __dict__: a função só funciona com objetos que possuem o atributo __dict__. Tipos primitivos como int, str, list não o possuem:

numero = 99
print(vars(numero))
# TypeError: vars() argument must have __dict__ attribute

2. Impacto de __slots__: classes que definem __slots__ não criam __dict__ em suas instâncias, tornando vars() inutilizável:

class Registro:
    __slots__ = ('id', 'timestamp')
    
    def __init__(self, id, timestamp):
        self.id = id
        self.timestamp = timestamp

reg = Registro(1, "2024-01-01")
print(vars(reg))
# AttributeError: 'Registro' object has no attribute '__dict__'

3. Modificação direta do dicionário: embora funcional, alterar atributos via vars() contorna mecanismos como property setters e validações encapsuladas. Prefira acessar atrbiutos diretamente ou utilizar métodos públicos do objeto.

4. Comportamento de vars() sem argumentos vs locals(): em escopos de função, ambas se comportam de modo equivalente. Porém, modificações no dicionário retornado podem não ser refletidas no escopo real, pois o interpretador pode não reconhecer essas mudanças.

Tags: Python vars Introspecção __dict__ __slots__

Publicado em 6-27 22:53