2011-05-31 36 views
12

Quiero fusionar restricciones de las clases actuales y heredadas solo una vez que se carga una clase (¡no por objeto!).¿Cómo inicializar clases (no instancias) en Python?

class Domain(Validatable): 

    constraints = {...} 

Para ello he definido un método _initialize_class_not_instance que debe ser llamado una vez para cada clase:

class Validatable: 

    @classmethod 
    def _initialize_class_not_instance(cls): 
     # merge constraints from derived class and base classes 
     pass 

    __class__._initialize_class_not_instance() # doesn't work 
    # Validatable._merge_constraints() # doesn't work too 

El problema es que __class__ no existe en este contexto y Validatable no está definido también. Pero quiero evitar que el usuario de mi API tenga que llamar explícitamente al método de inicialización o tenga que usar un decorador de clases adicional.

¿Alguna idea de cómo inicializar la clase?

+0

Tenga en cuenta que las clases ** son ** instancias, por lo general son instancias de 'tipo' pero como @Ignacio ha señalado que pueden ser instancias de una subclase personalizada de' tipo'. – Duncan

Respuesta

1

que terminó con un decorador clase y sin herencia. Este decorador fusiona las limitaciones de las clases actuales y heredados y anula la __init__ método:

def validatable(cls): 

    # merge constraints from derived class and base classes here ... 

    original_init = cls.__init__ 
    def init_to_insert(self, *args, **keywords): 
     self.errors = {} 
     original_init(self, *args, **keywords) 
    cls.__init__ = init_to_insert 
    return cls 

Esta es la clave para mi solución, ya que el decorador tiene que modificar la clase (la fusión de las limitaciones y la inserción de los métodos) e instancias.

16

Usa una metaclase.

class MetaClass(type): 
    def __init__(cls, name, bases, d): 
    type.__init__(cls, name, bases, d) 
    cls.foo = 42 

class MyClass(object): 
    __metaclass__ = MetaClass 

print MyClass.foo 
+8

para el registro, en python3, es 'MyClass (object, metaclass = MetaClass)' – ninjagecko

+0

¿Por qué necesita MetaClass? ¿Por qué no simplemente poner la declaración "MyClass.foo = 42" después de la definición de "MyClass"? –

Cuestiones relacionadas