On Wed, 06 Jul 2005 17:57:42 +0200, Thomas Heller <[EMAIL PROTECTED]> wrote:
>I'm trying to implement __iter__ on an abstract base class while I don't >know whether subclasses support that or not. >Hope that makes sense, if not, this code should be clearer: > >class Base: > def __getattr__(self, name): > if name == "__iter__" and hasattr(self, "Iterator"): > return self.Iterator > raise AttributeError, name > >class Concrete(Base): > def Iterator(self): > yield 1 > yield 2 > yield 3 > >The idea is that if a subclass of Base defines an 'Iterator' method, >instances are iterable. They are not iterable otherwise. > >The above gives the expected behaviour: iter(Base()) raises a >"TypeError: iteration over non-sequence", and iter(Concrete()) returns a >generator. > >If, however, I make Base a newstyle class, this will not work any >longer. __getattr__ is never called for "__iter__" (neither is >__getattribute__, btw). Probably this has to do with data descriptors >and non-data descriptors, but I'm too tired at the moment to think >further about this. > >Is there any way I could make the above code work with new style >classes? Will a property or custom descriptor do what you want? E.g. >>> class Base(object): ... def __getIter(self): ... if hasattr(self, "Iterator"): ... return self.Iterator ... raise AttributeError, name ... __iter__ = property(__getIter) ... >>> class Concrete(Base): ... def Iterator(self): ... yield 1 ... yield 2 ... yield 3 ... >>> iter(Base()) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: iteration over non-sequence >>> iter(Concrete()) <generator object at 0x02EF152C> >>> list(iter(Concrete())) [1, 2, 3] Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list