2012-06-29 13 views
6

Digresión inicio¿Qué hay de malo con esta simple metaclase de python?

que acaba de aprender lo que son metaclases en Python. No creo que los creadores de Python quisieran que todos los usen. Quiero decir algo: una metaclass que podría no ser una clase en la mayoría de los casos es suficiente para desviar a la mayoría de la gente de este concepto.

final Digresión

a mi pregunta. Escribí esta metaclase simple para agregar una cadena de documentación predeterminada a todas las clases que se crean en el módulo. Pero no está funcionando:

def metest(cls,name,bases,dict): 
    cls.setattr(cls,'__doc__',"""Default Doc""") 
    return type(cls,(),{}) 

__metaclass__=metest 

class test(object): 
    pass 

print test.__doc__ 

t=test() 

print t.__doc__ 

Salida:

None 
None 

¿Qué estoy haciendo mal?

Respuesta

3

he hecho tu trabajo ejemplo:

def metest(name, bases, dict): 
    print name, bases, dict 
    dict['__doc__'] = """New Doc""" 
    cls = type(name+"_meta", bases, dict) 
    return cls 

class Test(object): 
    "Old doc" 
    __metaclass__ = metest 

print Test 
print Test.__doc__ 

t = Test() 

print t.__doc__ 
  1. Hacer la "clase meta" que se utiliza.
  2. Corrija la firma de la "función de creación de clase". El cls será creado por nosotros.
  3. Disponer de un "viejo" y un "nuevo" docstring para distinguir.
+0

Es posible usar una metaclase global, simplemente no heredes de 'object' –

+0

¿Quién no debería heredar de un objeto? ¿La metaclase o TODAS las clases en el módulo? – ritratt

2

Ver esta respuesta: Python metaclass and the object base class

Proporcionar la clase de base object anula la metaclase de nivel de módulo y lo reemplaza con type (la metaclase de object).

Además, su metaclase está defectuosa y no funcionará incluso si la aplica (estableciendo __metaclass__ dentro de la clase). Solo debe aceptar tres argumentos. Suele ver ejemplos que aceptan cuatro, pero eso es porque la metaclase suele ser, adivina qué, una clase , por lo que acepta un argumento "propio" extra (que por convención se llama cls para metaclases).

4

No estoy del todo familiarizado con el enfoque global que está haciendo, estableciendo __metaclass__ así. Por lo que sé, es otro estilo válido.

Pero voy a dar un ejemplo de lo que estoy familiarizado con:

class MeTest(type): 
    def __new__(cls,name,bases,dict): 
     dict['__doc__'] = """Default Doc""" 
     return type.__new__(cls,name,bases,dict) 

class Test(object): 
    __metaclass__ = MeTest 
+0

Quiero hacerlo usando una función como la metaclase. – ritratt

1

Posiblemente esto es lo que desea. Heredando de object haría que la metaclase type, por lo que no puede hacerlo si desea utilizar una metaclase mundial

def metest(name, bases, dct): 
    dct['__doc__'] = """Default Doc""" 
    return type(name, bases, dct) 

__metaclass__=metest 

class test: 
    pass 

print test.__doc__ 

t=test() 

print t.__doc__ 
+0

Pero, ¿no debería la metaclase ser necesariamente un tipo? Porque por lo que he entendido, todas las clases en Python son objetos de la clase 'tipo'. Entonces, si quiero alterar todas las clases, entonces necesito anular el 'tipo', que es lo que' metaclass' hace. Entonces, ¿por qué NO debo heredar de 'type'? ¿Es porque hereda de la clase 'type' no invalidada? Estoy confundido. : S – ritratt

+0

@ritratt, 'metest' es una función que devuelve una clase que _ hereda de type_. La '' __metaclass __meiter' global solo funciona para las clases clásicas. Una vez que heredas de 'object' estás configurando la metaclase a' type' a menos que la clase anule la metaclase otra vez –

1

Su metaclase de nivel de módulo se anula, tal como se ha dicho anteriormente por BrenBarn. Para solucionar esto, intente codificarlo en return cls en lugar de establecerlo como una instancia de clase.

Cuestiones relacionadas