Curso
Uma metaclass em Python é a classe das classes — ela define como uma classe se comporta. Uma classe, por sua vez, é uma instância de uma metaclass. Em Python, uma classe define como as instâncias dessa classe vão se comportar. Para entender bem metaclasses, é importante já ter experiência trabalhando com classes em Python. Antes de mergulhar no tema, vamos tirar alguns conceitos do caminho.
Tudo em Python é um objeto
class TestClass():
pass
my_test_class = TestClass()
print(my_test_class)
<__main__.TestClass object at 0x7f6fcc6bf908>
Classes em Python podem ser criadas dinamicamente
type em Python permite descobrir o tipo de um objeto. Vamos verificar o tipo do objeto que criamos acima.
type(TestClass)
type
type(type)
type
Espera aí, o que foi isso? A gente esperaria que o tipo do objeto criado acima fosse class, mas não é. Guarda essa ideia — já já a gente volta nela. Também percebemos que o tipo de type é type. Ou seja, ele é uma instância de type. Outra coisa interessante que type faz é permitir criar classes dinamicamente. Veja como fazer isso abaixo. A classe DataCamp mostrada abaixo poderia ser criada usando type assim:
class DataCamp():
pass
DataCampClass = type('DataCamp', (), {})
print(DataCampClass)
print(DataCamp())
<class '__main__.DataCamp'>
<__main__.DataCamp object at 0x7f6fcc66e358>
No exemplo acima, DataCamp é o nome da classe, enquanto DataCampClass é a variável que guarda a referência da classe. Ao usar type, podemos passar atributos da classe via um dicionário, como abaixo:
PythonClass = type('PythonClass', (), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass.start_date, PythonClass.instructor)
print(PythonClass)
August 2018 John Doe
<class '__main__.PythonClass'>
Se quisermos que a nossa PythonClass herde da classe DataCamp, passamos essa classe como segundo argumento ao definir com type:
PythonClass = type('PythonClass', (DataCamp,), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass)
<class '__main__.PythonClass'>
Com esses dois conceitos em mente, fica claro que o Python cria classes usando uma metaclass. Vimos que tudo em Python é um objeto — e esses objetos são criados por metaclasses. Sempre que usamos class para criar uma classe, existe uma metaclass fazendo a mágica por trás dos panos. Já vimos o type fazendo isso na prática. É parecido com str, que cria strings, e int, que cria inteiros. Em Python, o atributo ___class__ permite verificar o tipo da instância atual. Vamos criar uma string e checar seu tipo:
article = 'metaclasses'
article.__class__
str
Também podemos checar o tipo usando type(article).
type(article)
str
Ao verificar o tipo de str, descobrimos que ele é type.
type(str)
type
O mesmo acontece ao verificar float, int, list, tuple e dict. Todos esses objetos são do tipo type.
print(type(list),type(float), type(dict), type(tuple))
<class 'type'> <class 'type'> <class 'type'> <class 'type'>
Já vimos que type cria classes. Portanto, quando verificamos o __class__ de __class__, o retorno deve ser type.
article.__class__.__class__
type
Domine suas habilidades em dados com o DataCamp
Mais de 10 milhões de pessoas aprendem Python, R, SQL e outras habilidades tecnológicas usando nossos cursos práticos elaborados por especialistas do setor.

Criando metaclasses personalizadas
Em Python, dá para personalizar o processo de criação de classes passando a palavra-chave metaclass na definição da classe. Isso também pode ser feito herdando de uma classe que já define essa palavra‑chave.
class MyMeta(type):
pass
class MyClass(metaclass=MyMeta):
pass
class MySubclass(MyClass):
pass
Veja abaixo que o tipo da classe MyMeta é type e que o tipo de MyClass e MySubClass é MyMeta.
print(type(MyMeta))
print(type(MyClass))
print(type(MySubclass))
<class 'type'>
<class '__main__.MyMeta'>
<class '__main__.MyMeta'>
Quando nenhuma metaclass é definida, a metaclass padrão type é usada. Se uma metaclass for informada e não for uma instância de type(), então ela é usada diretamente como metaclass.
__new__ e __init__
Metaclasses também podem ser definidas de duas formas, como mostrado abaixo. Explicamos a diferença na sequência.
class MetaOne(type):
def __new__(cls, name, bases, dict):
pass
class MetaTwo(type):
def __init__(self, name, bases, dict):
pass
__new__ é usado quando você quer definir o dicionário (dict) ou a tupla de bases antes da criação da classe. O valor de retorno de __new__ geralmente é uma instância de cls. __new__ permite que subclasses de tipos imutáveis personalizem a criação de instâncias, e pode ser sobrescrito em metaclasses personalizadas para customizar a criação de classes. Já __init__ é chamado depois que o objeto foi criado, para inicializá‑lo.
Método __call__ da metaclass
De acordo com a documentação oficial, também é possível sobrescrever outros métodos de classe definindo um método __call__() personalizado na metaclass, permitindo um comportamento específico quando a classe é chamada.
Método __prepare__ da metaclass
Segundo o data model do Python
Após identificar a metaclass apropriada, o namespace da classe é preparado. Se a metaclass tiver o atributo __prepare__, ele é chamado como namespace = metaclass.__prepare__(name, bases, **kwds) (os argumentos nomeados adicionais, se houver, vêm da definição da classe). Se a metaclass não tiver __prepare__, o namespace da classe é inicializado como um mapeamento ordenado vazio. - docs.python.org
Padrão Singleton usando uma metaclass
Esse é um padrão de projeto que restringe a instanciação de uma classe a um único objeto. Pode ser útil, por exemplo, ao projetar uma classe de conexão com banco de dados, quando você quer manter apenas uma instância da conexão.
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonMeta,cls).__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonClass(metaclass=SingletonMeta):
pass
Conclusão
Neste artigo, você viu o que são metaclasses e como implementá‑las na sua programação em Python. Metaclasses podem ser aplicadas em logging, registro de classes no momento da criação, profiling, entre outros. Elas parecem conceitos bem abstratos — e talvez você esteja se perguntando se realmente precisa usá‑las. Tim Peters, veterano do Python, responde isso da melhor forma.
"Metaclasses são uma magia mais profunda do que 99% dos usuários deveria se preocupar. Se você está se perguntando se precisa delas, não precisa (as pessoas que realmente precisam sabem com certeza que precisam, e não precisam de explicações sobre o porquê)." - realpython
Quer aprender mais sobre Python? Comece a trilha de habilidades Python Programming da DataCamp e confira nosso tutorial de classes em Python.