2010-03-23 4 views
5

Aquí está mi problema. Quiero que la siguiente clase tenga muchos atributos de propiedad. Podría escribirlos todos como foo y bar, o basándome en algunos otros ejemplos que he visto, parece que podría usar un decorador de clases, una metaclase o anular el método __new__ para establecer las propiedades automágicamente. Simplemente no estoy seguro de cuál sería la forma "correcta" de hacerlo.¿Debo usar una metaclass, decorador de clase o anular el método __new__?

class Test(object): 
    def calculate_attr(self, attr): 
     # do calculaty stuff 
     return attr 

    @property 
    def foo(self): 
     return self.calculate_attr('foo') 

    @property 
    def bar(self): 
     return self.calculate_attr('bar') 
+2

En caso de duda, siempre van con simple y evidente. Si * usted * no puede entenderlo fácilmente, tampoco los tontos (como yo) a quienes se les pedirá que mantengan su código. –

+0

Cuando cambia la naturaleza de sus preguntas, generalmente lo mejor es abrir una nueva. –

Respuesta

4

Magic is bad. Hace que tu código sea más difícil de entender y mantener. Prácticamente nunca necesita metaclases o __new__.

Parece que su caso de uso podría ser implementado con código bastante sencillo (con sólo un pequeño toque de magia):

class Test(object): 
    def calculate_attr(self, attr): 
     return something 

    def __getattr__(self, name): 
     return self.calculate_attr(name) 
+1

@You prácticamente nunca necesita metaclases o '__new__': estoy totalmente en desacuerdo. En mi empresa ya habíamos tenido dos ocasiones, cuando teníamos una buena motivación para usar metaclases. Primero estaba creando una capa de abstracción para una base de datos personalizada que habíamos usado y la otra estaba creando nuestro propio sistema de modelo para ldap. Realmente no puedo entender, de dónde viene este resentimiento por las metaclases. Es un concepto fácil de comprender y realmente útil en ciertas situaciones. – gruszczy

+1

@gruszczy, las metaclases no son difíciles de entender, en realidad son una idea bastante fácil, aunque la sintaxis y el uso de ellas en Python hace que algunas personas tengan problemas. Sin embargo, son propensas a errores debido a la forma en que se propagan y, a veces, difíciles de combinar: no es automáticamente posible que una clase use dos metaclases en su construcción, incluso si esa es una operación perfectamente razonable. Este problema se ve agravado por el hecho de que las metaclases a menudo no están expuestas como parte de una API pública del sistema. –

2

de __new__ Una metaclase no se convierta en la __new__ para la clase de hacer-se utiliza para hacer la clase en sí. La metaclase devuelve el objeto de clase real . Una nueva instancia de una clase es devuelta por __new__.

en cuenta la (loco) siguiente código:.

def MyMetaClass(name, bases, dict): 
    print "name", name 
    print "bases", bases 
    print "dict", dict 
    return 7 

class C('hello', 'world'): 
    __metaclass__ = MyMetaClass 

    foo = "bar" 

    def baz(self, qux): 
     pass 

print "C", C 

(He utilizado una función en lugar de una clase como la metaclase Cualquier exigible puede ser utilizado como una metaclase, pero muchas personas optan por derecho suyo como clases que heredan de type con nuevos overrided. Las diferencias entre una función que son sutiles.)

genera

name C 
bases ('hello', 'world') 
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>} 
C 7 

¿Te ayuda a comprender mejor qué metaclases son?

muy raramente necesita definir una metaclase propia.

+0

¿No debería ser ese "objeto de clase real" en lugar de "realmente objeto de clase"? –

1

Metaclass se usa cuando se crea una nueva clase, no una instancia. De esta forma puede, por ejemplo, registrar clases (django lo hace y lo usa, por ejemplo, para crear tablas en la base de datos). Desde class es una instrucción que puede considerar como decorador de una clase.

Cuestiones relacionadas