El día 28 de agosto de 2013 01:44, Olemis Lang <ole...@gmail.com> escribió: > Busco una librería q implemente un mecanismo de extensión similar a > los traits (self, scala, smalltalk, ...) . Lo q necesito es extender > el comportamiento de clases sin herencia múltiple i.e. mixins . Si el > mecanismo funciona a nivel d objetos en vez d clases puede q m sirva > también . > > En mi corta investigación he encontrado : > > - https://pypi.python.org/pypi/strait : en la línea d lo q necesito hacer > pero no permite redefinición (overrides) ni encadenamiento. > - http://pypi.python.org/pypi/Traits : > - https://pypi.python.org/pypi/simpletraits : lejanamente > parecido a lo q quiero hacer , creo q ni siquiera tiene q ver ... > > ¿Alguien conoce otra librería o alguna otra variante q pueda recomendar?
Viendo estas referencias, hay quién confunde "traits" con la programación por contrato. Un trait define un comportamiento determinado mediante: - Métodos "concretos" que implementan un comportamiento determinado - Métodos "abstractos" que parametrizan un comportamiento determinado En scala, los traits son similares a las clases abstractas de java, con la excepción de que también pueden tener métodos concretos. Del mismo modo, en python puedes usar las clases abstractas base (ABC). Mediante el uso de la metaclase abc.ABCMeta se pueden crear clases abstractas virtuales que funcionen como traits. Mejor lo vemos con un ejemplo (para python3): from abc import ABCMeta, abstractmethod class Trait(ABCMeta): pass class MyTrait(metaclass=Trait): @abstractmethod def __str__(self): return "" def print(self): print(">>"+self.__str__()+"<<") Hemos definido un trait 'MyTrait' con un métodos abstracto y otro concreto. Para usarlo, empleamos la herencia múltiple: class MyClass(MyTrait): pass c=MyClass() ##ERROR: Clase abstracta no definida class MyClass(str, MyTrait): pass c=MyClass("HOLA") ##OK c.print() ## >>>HOLA<<< Supongo que ésto ya lo habías probado. Según pidés, no quieres "mixins", que equivaldría a que no quede rastro en el __mro__ . Se me ocurre complicar algo más Trait para que sea capaz de "inyectar" métodos: class Trait(ABCMeta): def __init__(self, name, bases, dic): self.__dic=dic def register(self, cls): super().register(cls) for k,v in self.__dic.items(): if not hasattr(cls,k): setattr(cls,k,v) return cls El modo de empleo de MyTrait sería como decorador: @MyTrait.register class MyClass(object): def __str__(self): return "MyTrait" assert(issubclass(MyClass, MyTrait)) assert(MyTrait not in MyClass.__mro__) c=MyClass() ##OK c.print() ## >>>MyTrait<<< El problema de este último sistema es que no tiene en cuenta los métodos abstractos ya que no está soportado añadir métodos abstractos dinámicamente. Como solución, se podría suplantar los métodos abstractos por una implementación que lanze una excepción "NotImplementedError" o similar. Supongo que se puede hacer mejor. Espero que te sirva. -- Hyperreals *R "Quarks, bits y otras criaturas infinitesimales": http://ch3m4.org/blog Buscador Python Hispano: http://ch3m4.org/python-es _______________________________________________ Python-es mailing list Python-es@python.org http://mail.python.org/mailman/listinfo/python-es FAQ: http://python-es-faq.wikidot.com/