2011-10-31 4 views
5

Después de leer el excelente SO post, probé la elaboración de una metaclase nivel de módulo:Python metaclase y la base objeto de clase

def metaclass(future_class_name, future_class_parents, future_class_attrs): 
    print "module.__metaclass__" 
    future_class_attrs["bar"]="bar" 
    return type(future_class_name, future_class_parents, future_class_attrs) 

__metaclass__=metaclass 


class Foo(object): 

    def __init__(self): 
     print 'Foo.__init__' 

f=Foo() 

esto no funciona (es decir "módulo metaclase" no se imprimen) a menos que elimine la clase base object de Foo. ¿Cómo?

NOTA: Estoy usando Python 2.6.1.

Respuesta

3

Heredar de objeto trae automáticamente el tipo metaclase junto con él. Esto anula su nivel de módulo __metaclass__ especificación.

Si se especifica la metaclase a nivel de clase, entonces objeto no anularlo:

def metaclass(future_class_name, future_class_parents, future_class_attrs): 
    print "module.__metaclass__" 
    future_class_attrs["bar"]="bar" 
    return type(future_class_name, future_class_parents, future_class_attrs) 

class Foo(object): 
    __metaclass__ = metaclass 

    def __init__(self): 
     print 'Foo.__init__' 

f=Foo() 

Ver http://docs.python.org/reference/datamodel.html?highlight=metaclass#customizing-class-creation

+0

La especificación no dice tal cosa. Lo que sí dice es que si hay una clase base, se usará la metaclase de la clase base, independientemente de si la clase base especifica o no una metaclase. – Marcin

2

La especificación specifies the order in which Python will look for a metaclass:

La metaclase apropiado está determinado por la siguiente precedencia reglas:

  • Si existe dict['__metaclass__'], se utiliza.
  • De lo contrario, si hay en menos una clase base, se usa su metaclase (esto busca primero un atributo __class__ y si no se encuentra, usa su tipo).
  • De lo contrario, si existe una variable global denominada __metaclass__, se utiliza.
  • De lo contrario, se utiliza la metaclase clásica de estilo antiguo (types.ClassType).

Va a ver de lo anterior que el tener una clase base en absoluto (cualquiera que sea la clase base es, aunque no acaba de heredar de object) adelanta el nivel de módulo __metaclass__.

Cuestiones relacionadas