Este artículo te proporcionará una breve descripción de lo que entendemos por una metaclase en Python y te mostrará algunos ejemplos de este concepto. Antes de introducirnos de lleno, debo señalar un punto importante sobre las clases en Python que hará que nos sea más sencillo comprender el concepto de metaclases.
¿Es una clase, un objeto en Python?
Si has programado ya en un lenguaje de programación que no sea Python, el concepto que entenderás de clases, probablemente sea el de una vía para crear nuevos objetos. Esto también es así en Python, pero Python incluso lo lleva un paso más lejos, ya que los objetos, ¡también se consideran clases!
Por lo tanto, si has creado la siguiente clase en Python:
class myClass(object): pass
Simplemente significa que un objeto con el nombre myClass ha sido creado en la memoria. Puesto que este objeto es capaz de crear nuevos objetos, se le considera una clase. Esto significa que podemos aplicar las operaciones de objetos en clases en Python, ya que las clases son objetos en si mismos.
Es por eso que podemos hacer operaciones en clases como, asignar una clase a una variable, de la siguiente manera:
class_object = myClass() print class_object
Lo cual devolvería:
< __main__.myClass object at 0x102623610 >
Incluso puedes pasar la clase myClass como un parámetro a un método, tal que así:
def class_object(object): print object class_object(myClass)
Lo que devolvería la siguiente salida:
< class '__main__.myClass' >
Metaclases
Seguramente ya te hayas topado con la palabra clave type en Python. Lo más probable es que la hayas utilizado para comprobar el tipo de un objeto, como puedes ver en los siguientes ejemplos:
print type('jorge') print type(100) print type(100.0) print type(int)
En cuyo caso obtendrás las siguientes salidas:
< type 'str' > < type 'int' > < type 'float' > < type 'type' >
En cuanto a las salidas, todo parece bastante claro hasta llegar al tipo type. Para ver lo que esto puede significar, volvamos a la clase que hemos definido al principio de este artículo:
class myClass(object): pass
Ahora, hacemos lo siguiente:
print type(myClass)
¿Qué obtenemos de esta sentencia? Asombrosamente:
< type 'type' >
Por lo tanto, podemos concluir que el tipo de las clases de Python es type.
¿Qué relación hay entre un tipo y una metaclase? Bueno, un tipo es una metaclase, siempre que la metaclase por defecto sea un tipo. Sé que esto puede ser confuso. Ese tipo se puede utilizar para devolver la clase de un objeto tal y como se ve más arriba, pero esto es debido a la compatibilidad con versiones anteriores de Python. Por lo tanto, si escribes:
print type(type)
Obtendrás:
< type 'type' >
Evidenciando que un tipo es un type.
El término metaclase (metaclass) simplemente significa algo así como algo que se ha creado para crear otras clases. En otras palabras, es la clase de una clase, lo que significa que la instancia de una clase en este caso es una clase. Type se considera una metaclase desde que la instancia de un tipo es una clase.
Por ejemplo, cuando hemos mencionado la siguiente sentencia más arriba:
class_object = myClass()
Esto simplemente construye un objeto/instancia de la clase myClass. En otras palabras, utilizamos una clase para crear un objeto.
De la misma forma, cuando hacemos:
class myClass(object): pass
Hemos utilizado la metaclase para crear la clase myClass (que se considera un tipo). Por lo tanto, al igual que el objeto es una instancia de una clase, una clase es una instancia de una metaclase.
Utilizando metaclases para crear una clase
En esta sección, veremos cómo podemos utilizar una metaclase para crear una clase, en lugar de utilizar la declaración de clase como hemos visto en el anterior tutorial sobre clases y objetos. Como vimos anteriormente, la metaclase por defecto es de tipo type. Por lo tanto, podemos utilizar la siguiente instrucción para crear una nueva clase:
new_class = type('myClass',(),{})
Si quieres hacer las cosas más simples, puedes asignar el mismo nombre de clase myClass al nombre de la variable.
Hemos utilizado un diccionario{} para definir los atributos de la clase. Por lo tanto, tendría la siguiente declaración:
myClass = type('myClass',(),{'a':True})
Similar a:
class myClass(object): a = True
Fuente: Abder-Rahman Ali