¿No debería __metaclass__ forzar el uso de una metaclase en Python?
-
03-07-2019 - |
Pregunta
He estado tratando de aprender acerca de las metaclases en Python. Tengo la idea principal, pero parece que no puedo activar el mecanismo. Como lo entiendo, puede especificar que M sea la metaclase cuando construya una clase K configurando __metaclass__
en M en el nivel global o de clase. Para probar esto, escribí el siguiente 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)
Sin embargo, cuando lo ejecuto, obtengo el siguiente 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
¿No debería ver "La lluvia en España"? después de 1 y 2? ¿Qué está pasando aquí?
Solución
En Python 3 (que está utilizando) las metaclases están especificadas por un parámetro de palabra clave en la definición de la clase:
class ClassMeta(metaclass=M):
pass
La especificación de una propiedad de clase __metaclass__
o una variable global es una sintaxis antigua de Python 2.x y ya no se admite. Consulte también " Novedades de Python 3 " y < a href = "http://www.python.org/dev/peps/pep-3115/" rel = "nofollow noreferrer"> PEP 2115 .
Otros consejos
Esto funciona como se espera en Python 2.6 (y versiones anteriores), pero en 3.0 las metaclases se especifican de forma diferente:
class ArgMeta(metaclass=M): ...
La sintaxis de las metaclases ha cambiado en Python 3.0. El atributo __metaclass__
ya no es especial ni en la clase ni en el nivel del módulo. Para hacer lo que intenta hacer, debe especificar metaclass
como un argumento de palabra clave para la declaración de class
:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta(metaclass=M): pass
Rendimientos:
1
The rain in Spain
Como es de esperar.