Python R2


Metaclases en Python

Posted in Python por Arturo Elias Antón en 16 septiembre 2008
Tags: , , , , , , ,

En programación orientada a objetos, una metaclase es una clase cuyas instancias son clases. En otras palabras, como los objetos son instancias de una clase, las clases con instancias de una metaclase. Las metaclases nos son útiles cuando tenemos que definir la clase en tiempo de ejecución.

Metaclases en Python

En Python las Metaclases son fáciles de implementar, gracias a __metaclass__. Un ejemplo de implementación del patrón “Singleton” con metaclase se puede ver en el archivo metaclass1.py:

#!/usr/bin/python
# Nombre : metaclass1.py

class Singleton(type):
    def __init__(cls, name, bases, dct):
        cls.__instance = None
        type.__init__(cls, name, bases, dct)

    def __call__(cls):
        if cls.__instance is None:
            cls.__instance = type.__call__(cls)
            return cls.__instance

class ClassObjetoUnico:
    __metaclass__ = Singleton

a = ClassObjetoUnico()
b = ClassObjetoUnico()

print a
print b

La salida de este script es es:

>>>
<__main__.ClassObjetoUnico object at 0x00C93FB0>
None

Este patrón es el que nos garantiza que solo allá una instancia de un tipo de objeto. En este ejemplo observamos que la metaclase Singleton hereda de la metaclase type, que se sobrescribe __call__ y __init__ en Singleton y que por último se le asigna a la __metaclass__ de la clase que quiero hacer única.

  • Todas las metaclass heredan de type.
  • El método __init__, se ejecuta cuando se instancia la metaclase.
  • El método __call__, se ejecuta cada vez que se intenta instanciar un objeto por medio de la clase.
  • Por último se le asigna el atributó especial __metaclass__ la metaclase Singleton, para crear la clase por medio de dicha metaclase.

Otro ejemplo de metaclase puede ser metaclase2.y:

#!/usr/bin/python
# Nombre : metaclass2.py

class AutoNot(type):
    def __init__(cls, name, bases, dct):
       type.__init__(cls, name, bases, dct)
       methods = [x for x in dct
                  if x[0:5] == "bool_"]
       def fx(x): setattr(cls, 'not_%s' % x,
                          lambda self: not dct[x](self))
       map(fx,methods)

class A(object):
    __metaclass__= AutoNot

    def __init__(self):
        self.id=1234

    def bool_false(self):
        return False

    def bool_true(self):
        return True

a = A()

print "a.bool_true()  =",a.bool_true()
print "a.bool_false() = ",a.bool_false()
print "a.not_bool_true()  =",a.not_bool_true()
print "a.not_bool_false() = ",a.not_bool_false()

El patrón Singleton se podría haber implementado sin la necesidad de Metaclases de la siguiente manera:

#!/usr/bin/python
# Nombre : singleton.py
class Singleton(object):
    _instance=None
    def __new__(cls):
        if not cls._instance:
            cls._instance=object.__new__(cls)
            return cls._instance
    def __init__(self):
        pass

a=Singleton()
b=Singleton()

print a
print b

En el ejemplo anterior vimos, como que se sobrescribe __new__, este método se ejecuta antes que __init__ y es el verdadero creador de la instancia de clase que luego será pasado a al método __init__. Si este método no devuelve la instancia nunca se ejecutara __init__ ya que el objeto nunca existirá.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: