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/

Reply via email to