Metaclasses em Python: Controle e Customização de Classes
Se você domina a Programação Orientada a Objetos e quer ir além, entender metaclasses é essencial para construir frameworks, bibliotecas ou APIs avançadas.
1. O que são Metaclasses
Uma metaclasse é uma classe que cria outras classes. Assim como objetos são instâncias de classes, classes são instâncias de metaclasses.
Por padrão, todas as classes Python são instâncias da metaclasse
type
.Você pode definir sua própria metaclasse para interceptar a criação de classes e modificar atributos, métodos ou comportamento.
Exemplo conceitual:
# Todas as classes são instâncias de 'type'
class MinhaClasse:
pass
print(type(MinhaClasse))
# Saída: <class 'type'>
MinhaClasse
é uma instância detype
.type
é a metaclasse padrão que cria classes em Python.
2. Criando uma Metaclasse Básica
Uma metaclasse é definida herdando de type
. O método mais importante é __new__
, que cria a classe, e __init__
, que inicializa a classe.
class MetaExemplo(type):
def __new__(mcs, nome, bases, dct):
print(f"Criando classe {nome}")
return super().__new__(mcs, nome, bases, dct)
class MinhaClasse(metaclass=MetaExemplo):
pass
# Saída:
# Criando classe MinhaClasse
Parâmetros de __new__
na metaclasse:
mcs
: a metaclasse (similar aself
em classes normais)nome
: nome da nova classebases
: tupla com classes basedct
: dicionário de atributos e métodos da classe
3. Usando Metaclasses para Customização
3.1 Adicionando métodos automaticamente
class AutoReprMeta(type):
def __new__(mcs, nome, bases, dct):
if '__repr__' not in dct:
def __repr__(self):
return f"<{nome} {self.__dict__}>"
dct['__repr__'] = __repr__
return super().__new__(mcs, nome, bases, dct)
class Pessoa(metaclass=AutoReprMeta):
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade
p = Pessoa("Ana", 28)
print(p)
# Saída: <Pessoa {'nome': 'Ana', 'idade': 28}>
A metaclasse adicionou automaticamente o método
__repr__
à classePessoa
se ele não existisse.
3.2 Validação de atributos
Podemos usar metaclasses para controlar atributos obrigatórios:
class ValidacaoMeta(type):
def __new__(mcs, nome, bases, dct):
if 'nome' not in dct:
raise TypeError(f"Classe {nome} deve definir atributo 'nome'")
return super().__new__(mcs, nome, bases, dct)
class Usuario(metaclass=ValidacaoMeta):
nome = "default"
# Se tentarmos criar sem 'nome', TypeError será lançado
Isso é útil em frameworks onde certos atributos ou métodos são obrigatórios, como em Django ou SQLAlchemy.
3.3 Registrando subclasses automaticamente
Metaclasses podem manter um registro de todas as subclasses:
class RegistryMeta(type):
registry = []
def __new__(mcs, nome, bases, dct):
cls = super().__new__(mcs, nome, bases, dct)
mcs.registry.append(cls)
return cls
class Base(metaclass=RegistryMeta):
pass
class A(Base):
pass
class B(Base):
pass
print(RegistryMeta.registry)
# Saída: [<class '__main__.Base'>, <class '__main__.A'>, <class '__main__.B'>]
Muito usado em plugins e frameworks, onde cada nova classe precisa ser registrada automaticamente.
4. Boas Práticas com Metaclasses
Não use metaclasses sem necessidade
Elas são poderosas, mas podem tornar o código difícil de entender.
Use para padrões de design complexos
Ex.: Singleton, registro de classes, frameworks de ORM.
Evite lógica pesada em
__new__
Prefira pequenas validações ou adições de métodos.
Combine metaclasses com mixins cuidadosamente
Certifique-se de que a ordem de herança e MRO não crie conflitos.
Documente claramente
Metaclasses podem confundir quem não conhece; uma boa documentação é essencial.
5. Cenários Avançados de Uso
5.1 Singleton com Metaclasses
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Config(metaclass=SingletonMeta):
pass
a = Config()
b = Config()
print(a is b) # True
Garantia de que apenas uma instância de Config existirá, útil em logs, configs e conexões de banco.
5.2 Frameworks e APIs
Django ORM utiliza metaclasses para criar classes de modelo dinamicamente.
SQLAlchemy usa metaclasses para mapear atributos Python para colunas de banco.
6. Conclusão
Metaclasses são classes que criam classes, permitindo controle completo sobre a criação e comportamento de classes.
Com metaclasses, podemos adicionar métodos automaticamente, validar atributos, registrar subclasses ou implementar padrões de design avançados como Singleton.
Devem ser usadas com cautela e propósito, geralmente em frameworks, bibliotecas ou sistemas complexos.
Combinadas com herança múltipla, mixins e programação orientada a objetos avançada, metaclasses tornam Python extremamente flexível e poderoso.
Comentários
Postar um comentário