Quem chama a metaclasse
Na verdade, isso decorre de uma discussão aqui no SO.
Versão curta
def meta(name, bases, class_dict)
return type(name, bases, class_dict)
class Klass(object):
__metaclass__ = meta
meta()
é chamado quandoKlass
declaração de classe é executada.
Qual parte do código (interno do python) realmente chamameta()
?
Versão longa
Quando a classe é declarada, algum código precisa fazer as verificações apropriadas dos atributos e verificar se há uma__metaclass__
declarado em um tipo. Se existir, ele deve executar uma chamada de método nessa metaclasse com o conhecido(class_name, bases, class_dict)
atributos. Não está realmente claro para mim qual código é responsável por essa ligação.
Eu fiz algumas pesquisas no CPython (veja abaixo), mas eu realmente gostaria de ter algo mais próximo de uma resposta definitiva.
Opção 1: ligou diretamente
A chamada de metaclasse é conectada à análise de classe. Se sim, existe alguma evidência disso?
Opção 2: é chamado portype.__new__()
Código emtype_call()
chamadastype_new()
que por sua vez chama_PyType_CalculateMetaclass()
. Isso sugere que a resolução da metaclasse é realmente feita durante a chamada paratype()
ao tentar descobrir qual valor retornartype()
Isso estaria de acordo com a noção de que uma "classe" é uma "callable que retorna um objeto"
Opção 3: Algo diferente
Todas as minhas suposições talvez estejam completamente erradas, é claro.
Alguns exemplos de casos apresentados no bate-papo:
Exemplo 1:
class Meta(type):
pass
class A:
__metaclass__ = Meta
A.__class__ == Meta
Isso é o queMeta.__new__()
retorna, então isso parece legítimo. A metaclasse se coloca comoA.__class__
Exemplo 2:
class Meta(type):
def __new__(cls, class_name, bases, class_dict):
return type(class_name, bases, class_dict)
class A(object):
__metaclass__ = Meta
A.__class__ == type
Editar 2: versão inicial correta, derivar corretamenteMeta
detype
.
Parece bem, mas não tenho certeza se isso faz o que acho que faz. Além disso: Qual é o método canônico para se comportar como no Exemplo 1?
Editar 3: Usandotype.__new__(...)
parece funcionar como esperado, o que também parece a favor da opção 2.
Alguém com um conhecimento mais profundo da magia interna dos python me esclarece?
Edit: A para uma cartilha bastante concisa nas metaclasses:http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/. Também possui alguns diagramas, referências e também destaca as diferenças entre python 2 e 3.
Edit 3: Existe uma boa resposta abaixo para o Python 3. O Python 3 usa__build_class__
para criar um objeto de classe. O caminho do código é diferente em Python 2.