O que são Metaclasses em Python?

Ana Maria Gomes
5 minutos de leitura

Conteúdos do tutorial

Entendendo Classes em Python

Antes de nos aprofundarmos no mundo das metaclasses, é essencial entender o básico sobre classes em Python. Diferentemente de muitas outras linguagens, Python trata classes como objetos. Esse conceito, emprestado do Smalltalk, significa que quando você define uma classe, Python cria um objeto baseado nessa definição.

Considere a seguinte classe simples:

class CriadorDeObjetos(object):
    pass

meu_objeto = CriadorDeObjetos()
print(meu_objeto)
Testar

Esse trecho de código não apenas define uma classe, mas também cria um objeto dessa classe. No entanto, a própria classe é um objeto também, e você pode:

  • Atribuí-la a uma variável
  • Anexar atributos a ela
  • Passá-la como parâmetro de uma função

Criando Classes Dinamicamente

Como as classes em Python são objetos, você pode criá-las dinamicamente. Você pode fazer isso dentro de uma função:

def escolher_classe(nome):
    if nome == 'foo':
        class Foo(object):
            pass
        return Foo
    else:
        class Bar(object):
            pass
        return Bar

MinhaClasse = escolher_classe('foo')
print(MinhaClasse)
print(MinhaClasse())

Mas Python também oferece uma maneira mais dinâmica de criar classes usando a função type. A função type pode atuar como uma fábrica de classes:

MinhaClasseBrilhante = type('MinhaClasseBrilhante', (), {})
print(MinhaClasseBrilhante)
print(MinhaClasseBrilhante())

Você pode até adicionar atributos e métodos à classe:

Foo = type('Foo', (), {'bar': True})
print(Foo.bar)

def echo_bar(self):
    print(self.bar)

FilhoDeFoo = type('FilhoDeFoo', (Foo,), {'echo_bar': echo_bar})
meu_foo = FilhoDeFoo()
meu_foo.echo_bar()

O que são Metaclasses?

Metaclasses são o que Python usa para criar objetos de classe. Elas podem ser pensadas como “fábricas de classes”. A função type embutida é na verdade uma metaclass que Python usa para criar todas as classes nos bastidores.

Quando você define uma classe com a palavra-chave class, Python usa a metaclass para criar o objeto de classe. Você pode ver isso examinando o atributo __class__ de um objeto:

class Bar(object): pass
b = Bar()
print(b.__class__.__class__)

A saída mostrará que o __class__ de qualquer classe é type, que é a metaclass embutida.

Metaclasses Personalizadas

Você pode criar suas próprias metaclasses subclassificando type. Metaclasses personalizadas podem modificar a criação de classes de várias maneiras, como registrar automaticamente a nova classe ou alterar atributos de classe.

Aqui está um exemplo simples de uma metaclass que transforma atributos de classe em maiúsculas:

class MetaclassAtributosMaiusculos(type):
    def __new__(cls, nome_classe, bases, attrs):
        attrs_maiusculos = {
            nome.upper(): valor for nome, valor in attrs.items() if not nome.startswith('__')
        }
        return super(MetaclassAtributosMaiusculos, cls).__new__(cls, nome_classe, bases, attrs_maiusculos)

class MinhaClasse(metaclass=MetaclassAtributosMaiusculos):
    bar = 'bip'

print(hasattr(MinhaClasse, 'bar'))  # False
print(hasattr(MinhaClasse, 'BAR'))  # True

Resumo

Metaclasses em Python são um conceito profundo que permite a criação e personalização dinâmica de objetos de classe. Embora possam ser poderosas, muitas vezes não são necessárias para a programação do dia a dia. Metaclasses são mais úteis ao criar APIs complexas ou frameworks que exigem um nível de dinamismo na criação de classes. Lembre-se, se você não tem certeza se precisa de metaclasses, provavelmente não precisa. No entanto, entendê-las pode oferecer uma visão mais aprofundada de como Python funciona por baixo dos panos.

Inscreva-se gratuitamente e fique atualizado

Receba toda semana um resumo dos principais conteúdos da Asimov direto no seu e-mail. 100% livre de spam.

Áreas de interesse: