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.