não deve __metaclass__ forçar o uso de uma metaclasse em Python?
-
03-07-2019 - |
Pergunta
Eu tenho tentado aprender sobre metaclasses em Python. Tenho a idéia principal, mas eu não consigo ativar o mecanismo. Pelo que entendi, você pode especificar M para ser como o metaclass ao construir uma classe K, definindo __metaclass__
a M no nível global ou classe. Para testar isso, eu escrevi o seguinte programa:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta:
__metaclass__ = M
p(2)
__metaclass__ = M
class GlobalMeta: pass
p(3)
M('NotMeta2', (), {})
p(4)
No entanto, quando eu executá-lo, eu recebo o seguinte resultado:
C:\Documents and Settings\Daniel Wong\Desktop>python --version Python 3.0.1 C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 1 2 3 The rain in Spain 4
eu não deveria ver "A chuva na Espanha" depois de 1 e 2? O que está acontecendo aqui?
Solução
Em Python 3 (que você está usando) metaclasses são especificados por um parâmetro de palavra-chave na definição da classe:
class ClassMeta(metaclass=M):
pass
A especificação de uma propriedade de classe __metaclass__
ou variável global é velha sintaxe de Python 2.x e não mais suportada. Veja também "O que há de novo no Python 3" e PEP 2115 .
Outras dicas
Isso funciona como esperado no Python 2.6 (e anteriores), mas em 3,0 metaclasses são especificados de forma diferente:
class ArgMeta(metaclass=M): ...
A sintaxe de metaclasses tem alterado em Python 3.0. O atributo __metaclass__
não é especial em qualquer classe, nem o nível de módulo. Para fazer o que você está tentando fazer, você precisa especificar metaclass
como um argumento de palavra-chave para a declaração class
:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta(metaclass=M): pass
Os rendimentos:
1
The rain in Spain
Como seria de esperar.