Tenho um amigo que gosta de usar metaclasses e regularmente as oferece como solução.
Penso que quase nunca é necessário usar metaclasses. Por quê? porque eu acho que se você está fazendo algo assim para uma classe, provavelmente deveria estar fazendo para um objeto. E um pequeno redesenho / refatoração está em ordem.
Ser capaz de usar metaclasses fez com que muitas pessoas em muitos lugares usassem classes como algum tipo de objeto de segunda categoria, o que parece desastroso para mim. A programação deve ser substituída por metaprogramação? O acréscimo de decoradores de classe infelizmente o tornou ainda mais aceitável.
Então, por favor, estou desesperado para saber seus casos de uso válidos (concretos) para metaclasses em Python. Ou para ficar esclarecido sobre por que classes mutantes são melhores do que objetos mutantes, às vezes.
Às vezes, ao usar uma biblioteca de terceiros, é útil poder alterar a classe de uma determinada maneira.
(Este é o único caso em que consigo pensar, e não é concreto)
Esta é uma grande pergunta. A julgar pelas respostas abaixo, é bastante claro que não existe um uso concreto para metaclasses.
— Marcus Ottosson
Eu tenho uma classe que lida com plotagem não interativa, como um frontend para Matplotlib. No entanto, às vezes alguém quer fazer plotagem interativa. Com apenas algumas funções, descobri que era capaz de incrementar a contagem de figuras, chamar desenhar manualmente, etc., mas precisava fazer isso antes e depois de cada chamada de plotagem. Portanto, para criar um wrapper de plotagem interativo e um wrapper de plotagem fora da tela, descobri que era mais eficiente fazer isso por meio de metaclasses, envolvendo os métodos apropriados, do que fazer algo como:
Este método não acompanha as mudanças da API e assim por diante, mas aquele que itera sobre os atributos da classe __init__antes de redefinir os atributos da classe é mais eficiente e mantém as coisas atualizadas:
Claro, pode haver maneiras melhores de fazer isso, mas descobri que isso é eficaz. Claro, isso também pode ser feito em __new__ou __init__, mas essa foi a solução que achei mais direta.
A mesma pergunta me foi feita recentemente e encontrei várias respostas. Espero que não haja problema em reviver este tópico, pois gostaria de elaborar alguns dos casos de uso mencionados e adicionar alguns novos.
A maioria das metaclasses que vi fazer uma de duas coisas:
Registro (adicionando uma classe a uma estrutura de dados):
Sempre que você cria uma subclasse Model, sua classe é registrada no modelsdicionário:
{'A': <__main__.A class at 0x...>,
'B': <__main__.B class at 0x...>}
Isso também pode ser feito com decoradores de classe:
Ou com uma função de registro explícita:
Na verdade, isso é praticamente o mesmo: você menciona decoradores de classe de maneira desfavorável, mas na verdade não é nada mais do que um açúcar sintático para uma invocação de função em uma classe, então não há mágica nisso.
De qualquer forma, a vantagem das metaclasses neste caso é a herança, pois elas funcionam para quaisquer subclasses, enquanto as outras soluções só funcionam para subclasses explicitamente decoradas ou registradas.
{'A': <__main__.A class at 0x...> # No B :(
Refatoração (modificação de atributos de classe ou adição de novos):
value.name = '%s.%s' % (name, key)
if hasattr(base, '_fields'):
Sempre que você cria uma subclasse Modele define alguns Fieldatributos, eles são injetados com seus nomes (para mensagens de erro mais informativas, por exemplo) e agrupados em um _fieldsdicionário (para facilitar a iteração, sem ter que examinar todos os atributos da classe e todas as suas classes básicas ' atributos todas as vezes):
{'foo': Integer('A.foo'), 'bar': String('B.bar')}
Novamente, isso pode ser feito (sem herança) com um decorador de classe:
value.name = '%s.%s' % (cls.__name__, key)
# B._fields is {'foo': Integer('A.foo')} :(
Ou explicitamente:
foo = Integer('A.foo')
_fields = {'foo': foo} # Don't forget all the base classes' fields, too!
Embora, ao contrário de sua defesa de não metaprogramação legível e sustentável, isso é muito mais complicado, redundante e sujeito a erros:
bar = String('bar')
_fields = {'B.bar': bar, 'A.foo': A.foo}
Tendo considerado os casos de uso mais comuns e concretos, os únicos casos em que você TEM absolutamente que usar metaclasses são quando você deseja modificar o nome da classe ou a lista de classes base, porque uma vez definidos, esses parâmetros são incorporados à classe, e nenhum decorador ou função pode desfazê-los.
return type.__new__(meta, 'foo', (int,), attrs)
Isso pode ser útil em estruturas para emitir avisos sempre que classes com nomes semelhantes ou árvores de herança incompletas são definidas, mas não consigo pensar em uma razão além de trollagem para realmente alterar esses valores. Talvez David Beazley possa.
De qualquer forma, no Python 3, as metaclasses também têm o __prepare__método, que permite avaliar o corpo da classe em um mapeamento diferente de um dict, suportando assim atributos ordenados, atributos sobrecarregados e outras coisas legais perversas:
# prints ['x', 'y'] rather than ['y', 'x']
print(attrs['foo'])
Você pode argumentar que os atributos ordenados podem ser obtidos com contadores de criação e a sobrecarga pode ser simulada com argumentos padrão:
Além de ser muito mais feio, também é menos flexível: e se você quiser atributos literais ordenados, como inteiros e strings? E se Nonefor um valor válido para x?
Esta é uma maneira criativa de resolver o primeiro problema:
print A._order # ['x', 'y']
E aqui está uma maneira criativa de resolver o segundo:
Mas isso é muito, MUITO vodu-er do que uma simples metaclasse (especialmente a primeira, que realmente derrete seu cérebro). Meu ponto é, você vê as metaclasses como estranhas e contra-intuitivas, mas você também pode vê-las como o próximo passo da evolução nas linguagens de programação: você só precisa ajustar sua mentalidade. Afinal, você provavelmente poderia fazer tudo em C, incluindo definir uma estrutura com ponteiros de função e passá-la como o primeiro argumento para suas funções. Uma pessoa vendo C ++ pela primeira vez pode dizer: "o que é essa mágica? Por que o compilador está passando implicitamentethisaos métodos, mas não às funções regulares e estáticas? É melhor ser explícito e prolixo sobre seus argumentos ". Mas então, a programação orientada a objetos é muito mais poderosa quando você a entende; e isso é, uh ... programação quase orientada a aspectos, eu acho. E assim que você entender metaclasses, elas são realmente muito simples, então por que não usá-las quando for conveniente?
E, finalmente, as metaclasses são radicais e a programação deve ser divertida. Usar construções de programação padrão e padrões de projeto o tempo todo é enfadonho e pouco inspirador e atrapalha sua imaginação. Viva um pouco! Aqui está uma metametaclasse, só para você.
cls._label = 'Made in %s' % meta.__name__
attrs['__new__'] = __new__
Esta é uma pergunta muito antiga, mas ainda está recebendo votos positivos, então pensei em adicionar um link para uma resposta mais abrangente. Se você gostaria de ler mais sobre metaclasses e seus usos, acabei de publicar um artigo sobre isso aqui .
— Dan Gittik
Essa é uma ótima resposta, obrigado pelo tempo escrevendo e dando vários exemplos
— Chen A.
"... a vantagem das metaclasses neste caso é a herança, já que funcionam para quaisquer subclasses" - não no Python 3, suponho? Acho que funciona no Python 2 apenas porque qualquer classe filha herda o __metaclass__atributo, mas esse atributo não é mais especial no Python 3. Existe alguma maneira de fazer com que essa coisa de "classes filhas também são construídas pela metaclasse do pai" funcione no Python 3 ?
— ForceBru 05 de
Isso também é verdadeiro para Python 3, porque uma classe B, herdada de A, cuja metaclasse é M, também é um tipo de M. Portanto, quando B é avaliado, M é invocado para criá-lo, e isso efetivamente permite que você para "trabalhar em quaisquer subclasses" (de A). Dito isso, o Python 3.6 introduziu o muito mais simples init_subclass, então agora você pode manipular subclasses em uma classe base e não precisa mais de uma metaclasse para esse propósito.
Isso é brilhante, eu li tantos posts de blog sobre metaclasses, só que este aqui mostra os prós e contras e as alternativas à metaclasse.
O propósito das metaclasses não é substituir a distinção classe / objeto por metaclasse / classe - é mudar o comportamento das definições de classe (e, portanto, suas instâncias) de alguma forma. Efetivamente, é para alterar o comportamento da instrução de classe de maneiras que podem ser mais úteis para seu domínio específico do que o padrão. As coisas para as quais eu os usei são:
Subclasses de rastreamento, geralmente para registrar manipuladores. Isso é útil ao usar uma configuração de estilo de plug-in, onde você deseja registrar um manipulador para uma coisa específica simplesmente criando uma subclasse e configurando alguns atributos de classe. por exemplo. suponha que você escreva um manipulador para vários formatos de música, onde cada classe implementa métodos apropriados (reproduzir / obter tags etc.) para seu tipo. Adicionar um manipulador para um novo tipo torna-se:
A metaclasse, então, mantém um dicionário de {'.mp3' : MP3File, ... }etc, e constrói um objeto do tipo apropriado quando você solicita um manipulador por meio de uma função de fábrica.
Mudança de comportamento. Você pode querer atribuir um significado especial a certos atributos, resultando em comportamento alterado quando eles estão presentes. Por exemplo, você pode querer procurar métodos com o nome _get_fooe _set_fooconvertê-los em propriedades de forma transparente. Como um exemplo do mundo real, aqui está uma receita que escrevi para fornecer definições de struct mais semelhantes ao C. A metaclasse é usada para converter os itens declarados em uma string de formato de estrutura, manipulando herança, etc., e produzir uma classe capaz de lidar com ela.
Para outros exemplos do mundo real, dê uma olhada em vários ORMs, como ORM de sqlalchemy ou sqlobject . Novamente, o objetivo é interpretar definições (aqui definições de coluna SQL) com um significado particular.
Bem, sim, rastreando subclasses. Mas por que você iria querer isso? Seu exemplo é apenas implícito para register_music_file (Mp3File, ['.mp3']), e a forma explícita é mais legível e sustentável. Este é um exemplo dos casos graves de que estou falando.
Sobre o caso ORM, você está falando sobre a maneira baseada em classes de definir tabelas, ou as metaclasses em objetos mapeados. Porque SQLAlchemy pode (corretamente) mapear para qualquer classe (e estou assumindo que ele não usa uma metaclasse para essa atividade).
Eu prefiro o estilo mais declarativo, em vez de exigir métodos de registro extras para cada subclasse - melhor se tudo estiver agrupado em um único local.
Para sqlalchemy, estou pensando principalmente na camada declarativa, então talvez sqlobject seja um exemplo melhor. No entanto, as metaclasses usadas internamente também são exemplos de reinterpretação semelhante de atributos específicos para declarar significado.
Desculpe, um dos meus comentários se perdeu no cenário de tempo limite do SO. Acho que as classes declarativas são quase uma abominação. Sei que as pessoas adoram e é um comportamento aceito. Mas (por experiência própria) eu sei que é inutilizável em uma situação onde você deseja declarar coisas pela ONU. Cancelar o registro de uma classe é difícil .
Vamos começar com a citação clássica de Tim Peter:
Metaclasses são mágicas mais profundas do que 99% dos usuários deveriam se preocupar. Se você se pergunta se precisa deles, não precisa (as pessoas que realmente precisam deles sabem com certeza que precisam deles e não precisam de uma explicação sobre o motivo). Tim Peters (clp post 2002-12-22)
Dito isso, tenho (periodicamente) encontrado usos verdadeiros de metaclasses. O que vem à mente é no Django, onde todos os seus modelos herdam de modelos.Modelo. models.Model, por sua vez, faz uma mágica séria para envolver seus modelos de banco de dados com as qualidades ORM do Django. Essa mágica acontece por meio de metaclasses. Ele cria todos os tipos de classes de exceção, classes de gerenciador, etc. etc.
Veja django / db / models / base.py, class ModelBase () para o início da história.
Bem, sim, entendo o ponto. Não me pergunto "como" ou "por que" usar metaclasses, me pergunto o "quem" e o "o quê". ORMs são um caso comum aqui eu vejo. Infelizmente, o ORM do Django é muito pobre comparado ao SQLAlchemy, que tem menos magia. Magia é ruim, e metaclasses realmente não são necessárias para isso.
Tendo lido a citação de Tim Peters no passado, o tempo mostrou que sua declaração é bastante inútil. Só depois de pesquisar metaclasses Python aqui no StackOverflow é que se tornou aparente como implementá-las. Depois de me forçar a aprender como escrever e usar metaclasses, suas habilidades me surpreenderam e me deram uma compreensão muito melhor de como o Python realmente funciona. As classes podem fornecer código reutilizável e as metaclasses podem fornecer aprimoramentos reutilizáveis ​​para essas classes.
Metaclasses podem ser úteis para a construção de linguagens específicas de domínio em Python. Exemplos concretos são Django, a sintaxe declarativa de SQLObject de esquemas de banco de dados.
Um exemplo básico de A Conservative Metaclass de Ian Bicking:
As metaclasses que usei foram principalmente para oferecer suporte a um tipo de estilo declarativo de programação. Por exemplo, considere um esquema de validação:
Algumas outras técnicas: Ingredientes para construir uma DSL em Python (pdf).
Editar (por Ali): Um exemplo de como fazer isso usando coleções e instâncias é o que eu preferiria. O fato importante são as instâncias, que fornecem mais potência e eliminam a razão de usar metaclasses. Além disso, vale a pena observar que seu exemplo usa uma mistura de classes e instâncias, o que certamente é uma indicação de que você não pode simplesmente fazer tudo com metaclasses. E cria uma maneira verdadeiramente não uniforme de fazer isso.
Não é perfeito, mas já existe quase zero de magia, nenhuma necessidade de metaclasses e uniformidade aprimorada.
Obrigado por isso. Este é um ótimo exemplo de caso de uso que considero desnecessário, feio e não gerenciável, que seria mais simples com base em uma instância de coleção simples (com coleções aninhadas conforme necessário).
@Ali A: você está convidado a fornecer um exemplo concreto de comparação lado a lado entre a sintaxe declarativa por meio de metaclasses e uma abordagem baseada em instância de coleção simples.
@Ali R: você pode editar minha resposta no local para adicionar um exemplo de estilo de coleção.
Ok, fiz isso. Desculpe, estou com um pouco de pressa hoje, mas tentarei responder a qualquer dúvida amanhã / tarde. Boas festas!
O segundo exemplo é feio, pois você teve que vincular a instância do validador com seu nome. Uma maneira um pouco melhor de fazer isso é usar um dicionário em vez de uma lista, mas, em Python, as classes são apenas açúcar de sintaxe para o dicionário, então por que não usar classes? Você obtém validação de nome gratuita também porque python babes não pode conter espaços ou caracteres especiais que uma string poderia.
Um padrão razoável de uso de metaclasse é fazer algo uma vez quando uma classe é definida, em vez de repetidamente sempre que a mesma classe é instanciada.
Quando várias classes compartilham o mesmo comportamento especial, repetir __metaclass__=Xé obviamente melhor do que repetir o código de propósito especial e / ou introduzir superclasses compartilhadas ad-hoc.
Mas mesmo com apenas uma classe especial e nenhuma extensão previsível, __new__e __init__de uma metaclasse são uma maneira mais limpa de inicializar variáveis ​​de classe ou outros dados globais do que misturar código de propósito especial defe classinstruções normais e no corpo de definição de classe.
— user412090
A única vez que usei metaclasses em Python foi ao escrever um wrapper para a API do Flickr.
Meu objetivo era extrair o site da API do flickr e gerar dinamicamente uma hierarquia de classes completa para permitir o acesso à API usando objetos Python:
Nesse exemplo, como eu gerei toda a API Python Flickr do site, realmente não sei as definições de classe em tempo de execução. Ser capaz de gerar tipos dinamicamente foi muito útil.
— Tríptico
Você pode gerar tipos dinamicamente sem usar metaclasses. >>> ajuda (tipo)
Mesmo se você não estiver ciente disso, estará usando metaclasses. tipo é uma metaclasse, na verdade o mais comum. :-)
— Veky
Eu estava pensando a mesma coisa ontem e concordo totalmente. As complicações no código causadas por tentativas de torná-lo mais declarativo geralmente tornam a base de código mais difícil de manter, mais difícil de ler e menos pythônica na minha opinião. Também normalmente requer muito copy.copy () ing (para manter a herança e copiar de classe para instância) e significa que você tem que olhar em muitos lugares para ver o que está acontecendo (sempre olhando da metaclasse para cima) que vai contra o grãos de python também. Eu tenho pesquisado o formencode e o código sqlalchemy para ver se esse estilo declarativo valeu a pena e claramente não. Esse estilo deve ser deixado para descritores (como propriedade e métodos) e dados imutáveis. Ruby tem um suporte melhor para esses estilos declarativos e estou feliz que a linguagem python principal não esteja seguindo esse caminho.
Eu posso ver seu uso para depuração, adicionar uma metaclasse a todas as suas classes base para obter informações mais ricas. Também vejo seu uso apenas em projetos (muito) grandes para se livrar de algum código clichê (mas com perda de clareza). sqlalchemy, por exemplo , os usa em outro lugar, para adicionar um método personalizado específico a todas as subclasses com base em um valor de atributo em sua definição de classe, por exemplo, um exemplo de brinquedo
poderia ter uma metaclasse que gerou um método nessa classe com propriedades especiais baseadas em "hello" (digamos um método que adicionou "hello" ao final de uma string). Pode ser bom para a manutenção ter certeza de que você não precisa escrever um método em cada subclasse que você fizer, ao invés disso, tudo que você precisa definir é method_maker_value.
A necessidade disso é tão rara e apenas reduz um pouco a digitação que não vale a pena considerar, a menos que você tenha uma base de código grande o suficiente.
— David Raznick
Você nunca precisa absolutamente usar uma metaclasse, uma vez que você sempre pode construir uma classe que faça o que você deseja usando a herança ou agregação da classe que deseja modificar.
Dito isso, pode ser muito útil em Smalltalk e Ruby ser capaz de modificar uma classe existente, mas Python não gosta de fazer isso diretamente.
Há um excelente artigo do DeveloperWorks sobre metaclasse em Python que pode ajudar. O artigo da Wikipedia também é muito bom.
Você também não precisa de objetos para fazer programação orientada a objetos - você poderia fazer isso com funções de primeira classe. Portanto, você não precisa usar objetos. Mas eles estão lá por conveniência. Portanto, não tenho certeza de que ponto você está tentando fazer no primeiro parágrafo.
Reveja a questão.
Algumas bibliotecas GUI têm problemas quando vários threads tentam interagir com elas. tkinteré um exemplo; e embora seja possível lidar explicitamente com o problema com eventos e filas, pode ser muito mais simples usar a biblioteca de uma maneira que ignore o problema por completo. Veja - a magia das metaclasses.
Ser capaz de reescrever dinamicamente uma biblioteca inteira sem problemas para que funcione corretamente como esperado em um aplicativo multithread pode ser extremamente útil em algumas circunstâncias. O módulo safetkinter faz isso com a ajuda de uma metaclasse fornecida pelo módulo threadbox - eventos e filas não são necessários.
Um aspecto interessante threadboxdisso é que ele não se importa com a classe que clona. Ele fornece um exemplo de como todas as classes básicas podem ser tocadas por uma metaclasse, se necessário. Um outro benefício que vem com as metaclasses é que elas também são executadas em classes herdadas. Programas que se escrevem - por que não?
O único caso de uso legítimo de uma metaclasse é impedir que outros desenvolvedores intrometidos mexam no seu código. Assim que um desenvolvedor intrometido dominar as metaclasses e começar a mexer nas suas, acrescente outro nível ou dois para mantê-los fora. Se isso não funcionar, comece a usar type.__new__ou talvez algum esquema usando uma metaclasse recursiva.
(escrito com ironia, mas já vi esse tipo de ofuscação ser feito. Django é um exemplo perfeito)
Não tenho certeza se a motivação era a mesma em Django.
— Ali Afshar,
Metaclasses não estão substituindo a programação! Eles são apenas um truque que pode automatizar ou tornar mais elegantes algumas tarefas. Um bom exemplo disso é a biblioteca de realce de sintaxe de Pigmentos . Ele tem uma classe chamada RegexLexerque permite ao usuário definir um conjunto de regras lexing como expressões regulares em uma classe. Uma metaclasse é usada para transformar as definições em um analisador útil.
Eles são como sal; é muito fácil de usar.
— Benjamin Peterson
Bem, na minha opinião, o caso dos Pigmentos é simplesmente desnecessário. Por que não ter apenas uma coleção simples como um dicionário, por que forçar uma classe a fazer isso?
Porque uma classe legal encapula a ideia de Lexer e tem outros métodos úteis como guess_filename (), etc.
A maneira como usei metaclasses foi para fornecer alguns atributos às classes. Considere por exemplo:
irá colocar o atributo name em cada classe que terá a metaclasse configurada para apontar para NameClass.
— hiperboreiano
Sim, funciona. Você também pode usar uma superclasse, que é pelo menos explícita e pode ser seguida no código. Sem interesse, para que você usou isso?
Este é um uso secundário, mas ... uma coisa para a qual considero as metaclasses úteis é para invocar uma função sempre que uma subclasse é criada. Codifiquei isso em uma metaclasse que procura por um __initsubclass__atributo: sempre que uma subclasse é criada, todas as classes pai que definem esse método são chamadas com __initsubclass__(cls, subcls). Isso permite a criação de uma classe pai que, em seguida, registra todas as subclasses com algum registro global, executa verificações invariáveis ​​nas subclasses sempre que são definidas, realiza operações de ligação tardia, etc ... tudo sem ter que chamar funções manualmente ou criar metaclasses personalizadas que desempenhar cada uma dessas funções separadas.
Veja bem, aos poucos comecei a perceber que a magia implícita desse comportamento é um tanto indesejável, já que é inesperado se olharmos para uma definição de classe fora do contexto ... então deixei de usar essa solução para qualquer coisa séria inicializando um __superatributo para cada classe e instância.
Recentemente, tive que usar uma metaclasse para ajudar a definir declarativamente um modelo SQLAlchemy em torno de uma tabela de banco de dados preenchida com dados do Censo dos EUA de http://census.ire.org/data/bulkdata.html
IRE fornece shells de banco de dados para as tabelas de dados do censo, que criam colunas inteiras seguindo uma convenção de nomenclatura do Census Bureau de p012015, p012016, p012017, etc.
Eu queria a) ser capaz de acessar essas colunas usando uma model_instance.p012017sintaxe, b) ser bastante explícito sobre o que estava fazendo ec) não precisar definir explicitamente dezenas de campos no modelo, então criei uma subclasse de SQLAlchemy DeclarativeMetapara iterar por meio de um intervalo de as colunas e criar automaticamente os campos do modelo correspondentes às colunas:
Eu poderia então usar essa metaclasse para a minha definição de modelo e acessar os campos enumerados automaticamente no modelo:
— Geoffrey Hing
Parece haver um uso legítimo descrito aqui - Reescrever Python Docstrings com uma Metaclass.
— mistermarko
Tive que usá-los uma vez para um analisador binário para torná-lo mais fácil de usar. Você define uma classe de mensagem com atributos dos campos presentes na transmissão. Eles precisavam ser ordenados da maneira como foram declarados para construir o formato final do fio a partir dele. Você pode fazer isso com metaclasses, se usar um dicionário de namespace ordenado. Na verdade, está nos exemplos para Metaclasses:
https://docs.python.org/3/reference/datamodel.html#metaclass-example
Mas em geral: avalie com muito cuidado se você realmente precisa da complexidade adicional das metaclasses.
— GeeF
a resposta de @Dan Gittik é legal
os exemplos no final podem esclarecer muitas coisas, mudei para python 3 e dou algumas explicações:
#China is metaclass and it's __new__ method would be changed by MetaMetaclass(metaclass)
class China(MetaMetaclass, metaclass=MetaMetaclass):
#Taiwan is metaclass and it's __new__ method would be changed by MetaMetaclass(metaclass)
class Taiwan(MetaMetaclass, metaclass=MetaMetaclass):
#A is a normal class and it's __new__ method would be changed by China(metaclass)
class A(metaclass=China):
#B is a normal class and it's __new__ method would be changed by Taiwan(metaclass)
class B(metaclass=Taiwan):
print(A._label)  # Made in China
print(B._label)  # Made in Taiwan
tudo é objeto, então classe é objeto
objeto de classe é criado por metaclasse
toda classe herdada do tipo é metaclasse
metaclasse poderia controlar a criação de classes
metaclasse pode controlar a criação de metaclasse também (para que possa fazer um loop para sempre)
isso é metaprogramação ... você pode controlar o sistema de tipos em tempo de execução
novamente, tudo é objeto, este é um sistema uniforme, tipo criar tipo e tipo criar instância
— gaiola
Outro caso de uso é quando você deseja modificar atributos de nível de classe e ter certeza de que isso afeta apenas o objeto em questão. Na prática, isso implica "mesclar" as fases de metaclasses e instanciações de classes, levando você a lidar apenas com as instâncias de classe de seu próprio tipo (exclusivo).
Eu também tive que fazer isso quando (por questões de legibilidade e polimorfismo ) queríamos definir dinamicamente property s cujos valores retornados (podem) resultar de cálculos baseados em atributos de nível de instância (frequentemente alterados), o que só pode ser feito no nível de classe , ou seja , após a instanciação da metaclasse e antes da instanciação da classe.