Buenos dias, para empezar, Yeiniel, por favor, tuteame que si me siento mas viejo ;)
Siguiendo con el tema, lo que tenía yo en mente, era el segundo caso que has citado en el mensaje anterior: esto es B quiere exponer una funcionalidad F. Al respecto, un ejemplo, sería poder añadir conectividad con BBDD sin tener que modificar la clase B. El decorador se encargaria de gestionar la conexión y ejecutar las querys. Quizá este no sea el mejor ejemplo ( yo no lo haría de esa manera ) pero creo que resume bien lo que planteé en el primer mensaje. Simplificando, el código sería el siguiente: class Decor(object): '''Decora la clase para anadir funcionalidades''' def __init__(self, arg): self.arg = arg print "Clase decoradora" print self.arg def __call__(self, cls): class Wrapper(cls): classattr = self.arg print "En wrapper de clase decoradora" def my_method(self, value): print "New my method {0}, conn string: {1}".format(value, self.classattr) def new_method(self, value): print "New new method {0}".format(value) return Wrapper @Decor('mysql') class B(object): def __init__(self, nombre): self.nombre = nombre print "Creo objeto B" def show_name(self): print "My nombre es {0}".format(self.izena) def __call__(self): print "Inside call" a = B('Ander') a.my_method('Ander') a.new_method('Ander2') El código es válido y anade las funciones a la clase decorada, pero no me acaba de gustar y es por eso por lo que formulé la pregunta. Un saludo. Ander. El día 22 de octubre de 2013 14:50, Yeiniel Suárez Sosa <yein...@uclv.cu> escribió: > Hola nuevamente > Yo normalmente no escribo en esta lista, lo cual es malo para la comunidad y > me disculpo, pero estoy haciéndolo ahora porque el tema es teórico y merece > la pena (al menos desde mi punto de vista) lograr buenas prácticas en la > comunidad. > > Ander Garmendia > en el post original usted dice que quiere añadir una funcionalidad F a una > clase B. Aquí es necesario dejar bien claro si el problema es que B necesita > la funcionalidad F para hacer su trabajo o si B tiene que exponer la > funcionalidad F. En el primer caso estamos tratando con un problema de > dependencia, del cual expuse mi forma de tratarlo. Si el problema es que B > necesita exponer a F, bueno el problema es otro, porque todo depende de que > tipo de elemento es F. La herencia es para crear objetos que son una > especialización de otro más general, que B herede de C solo es correcto si B > es un caso especifico de C, de lo contrario la herencia no tiene sentido. En > el caso de que B necesite exponer un método de C pero no es una > especialización de esta clase, entonces el problema todavía es de > dependencia (composición) y no de herencia. > > ahh, se me olvidaba, la sintaxis correcta para inyectar atributos a la clase > es la de Juan, saludos para el > > Hernan M. F > Particularmente encuentro el ejemplo que presentas como poco elegante. > Porque en ese caso la clase C tiene una dependencia fija en el código al > método F() de la clase D la cual no puede ser modificada (bueno, si puede > ser modificada empleando settatr(), lo que hace a Python excelente desde mi > punto de vista). La cuestión es que se programa una vez, pero se modifica el > código y se revisa múltiples veces y en este caso el usuario de C tiene que > leer todo el código para darse cuenta de que cambiar si necesita reemplazar > D.F por otra cosa. Y finalmente si F es una función que no dependa de que > argumentos reciba D en el constructor, entonces no es necesario que sea > miembro de la clase D. Yo pondría tu ejemplo de la siguiente forma: > > class C: > def __init__(self, f=None): > if f is None: > d = D() > f = d.f > > settatr(self, 'f', f) > > def f(self): > raise NotImplementedError() > > Esta variante le deja claro al usuario que solo con parametrizar la clase C > puede reemplazar la maquinaria externa que consume la clase. Finalmente > quiero decir (mi criterio nuevamente y el de algunas personas que asi lo > ponen en sus blogs) que la herencia multiple no es la forma de inyectar > comportamiento en una clase y que debe ser usada con mucho cuidado. Herencia > es herencia, una persona hereda de animal pero un navegador web no hereda de > conexión de red solo porque la use y la herencia lo pueda hacer parecer que > funciona. > > Atentamente > Ing. Yeiniel Suárez Sosa > Profesor Instructor, Dep. Automática y Sistemas Computacionales > Facultad de Ingeniería Eléctrica, Universidad Central "Marta Abreu" de las > Villas (UCLV) > > > On 2013-10-22 04:14, Hernan M. F. wrote: >>> >>> gracias a todos por el interes. Creo que me ha quedado bastante claro el >>> asunto. >>> >>> - Yeiniel me ha gustado tu solución, solo que yo la utilizaría con la >>> sintaxis que ha utilizado Juan. >>> - Sergio, no estoy intentando resolver ningún problema, solamente >>> estoy "jugando" con los decoradores y viendo de lo que son capaces. Y >>> mi pregunta surge desde ese interes. >>> - Y enlazando la frase anterior, gracias Txema por tu post, ya que >>> bien explicas para que son bueno los decoradores y para que no. >> >> >> Ten cuidado cuando cambies el comportamiento de objetos al vuelo. >> >> Si vas a componer clases ¿por qué complicarse?. Usa lo estándar: >> class C (B): >> def __init__(self): >> self._f_provider = D() >> def F(self): >> self._f_provider.F() >> >> Tampoco estás obligado a definir una clase y usar métodos, esto no es >> Java. >> F() podría ser un procedimiento o función de un módulo. >> >> Con la herencia múltiple de Python (que a veces se nos olvida que tiene), >> sería: >> 'class C (B,D)' y no tienes que hacer mas nada. Eso sí, te compras >> otros ocho mil >> problemas nuevos… >> >> Y si el problema y el marco de la solución lo merece lo mas formal es usar >> abc. >> >> Keep it simple. ;-) >> >>> >>> El día 21 de octubre de 2013 18:48, Txema Vicente <tx...@nabla.net> >>> escribió: >>>> >>>> Buenas. >>>> >>>> Aunque puedas usar decoradores para ampliar la clase que decoran, yo no >>>> veo >>>> los decoradores como sustitutos de la herencia, ni ninguna reduccion de >>>> codigo. >>>> >>>> No necesitas decoradores para hacer eso, puedes asignar una funcion a un >>>> atributo de la clase (B.F = F). Ademas, como te pongas a crear clases >>>> decoradas que se amplian en ejecucion, a ver como lo explicas luego. >>>> >>>> Los decoradores vienen bien, por ejemplo, para "enchufar" funciones que >>>> van >>>> a manejar algo, como funciones que van a tratar los eventos de un GUI, o >>>> responder en una ruta URL @ruta("/admin"). Dependiendo de lo que quieras >>>> hacer, sera con una funcion o con una clase, con argumentos o sin ellos. >>>> >>>> Tambien tienes el decorador @classmethod por si quieres crear clases que >>>> puedan tener casos particulares (miclase = B.ampliada_con_F()), o actuar >>>> como "factoria" de clases. >>>> Y @staticmethod, que yo solo lo uso en raras ocasiones por motivos de >>>> organizacion de API. >>>> >>>> La herencia es algo claro y maravilloso que te permite organizar las >>>> cosas. >>>> El decorador es un "atajo del idioma" para trastear con las funciones, >>>> no >>>> hay nada que realmente no puedas hacer sin usarlo. >>>> >>>> >>>> El 21/10/2013 15:37, Ander Garmendia escribió: >>>> >>>> Buenas, >>>> >>>> estoy 'jugando' con decoradores y haciendo diferentes pruebas y tengo >>>> una duda que quizá alguien me pueda aclarar. >>>> >>>> Digamos que tenemos una clase ( llamemosla B ) a la que queremos >>>> añadir una funcionalidad (llamemosla F). El método clásico sería >>>> heredar desde la clase base ( B ) y crear una nueva clase ( llamemosla >>>> C ) que implementase nuestra funcionalidad ( F ). Hasta aquí todo >>>> normal y corriente. >>>> >>>> Ahora llega python y nos ofrece los decoradores, por lo tanto, podemos >>>> crear una clase decoradora ( llamemosla D ) que implemente la >>>> funcionalidad ( F ) y que decorando una clase ( volvamos a la clase B >>>> ), añade la funcionalidad F en la clase B sin necesidad de herencias >>>> de ningún tipo. >>>> >>>> Visto así, todo parece muy cómodo, se escribe menos código, hay menos >>>> clases implicadas, etc. >>>> Y como todo parece muy bonito, aquí surge mi duda: ¿Está esta practica >>>> extendida al escribir código en python ( es pythonico y aceptable ) ? >>>> ¿ o es mas una prueba conceptual ? >>>> >>>> Gracias de antemano y un saludo. >>>> >>>> Ander. >>>> _______________________________________________ >>>> Python-es mailing list >>>> Python-es@python.org >>>> https://mail.python.org/mailman/listinfo/python-es >>>> FAQ: http://python-es-faq.wikidot.com/ >>>> >>>> >>>> >>>> >>>> _______________________________________________ >>>> Python-es mailing list >>>> Python-es@python.org >>>> https://mail.python.org/mailman/listinfo/python-es >>>> FAQ: http://python-es-faq.wikidot.com/ >>>> >>> _______________________________________________ >>> Python-es mailing list >>> Python-es@python.org >>> https://mail.python.org/mailman/listinfo/python-es >>> FAQ: http://python-es-faq.wikidot.com/ >> >> >> _______________________________________________ >> Python-es mailing list >> Python-es@python.org >> https://mail.python.org/mailman/listinfo/python-es >> FAQ: http://python-es-faq.wikidot.com/ > > > -- > > _______________________________________________ > Python-es mailing list > Python-es@python.org > https://mail.python.org/mailman/listinfo/python-es > FAQ: http://python-es-faq.wikidot.com/ _______________________________________________ Python-es mailing list Python-es@python.org https://mail.python.org/mailman/listinfo/python-es FAQ: http://python-es-faq.wikidot.com/