Conditionally implementing __iter__ in new style classes

Thomas Heller theller at python.net
Wed Jul 6 12:07:10 EDT 2005


Thomas Heller <theller at python.net> writes:

> 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?

I forgot to mention this: The Base class also implements a __getitem__
method which should be used for iteration if the .Iterator method in the
subclass is not available.  So it seems impossible to raise an exception
in the __iter__ method if .Iterator is not found - __iter__ MUST return
an iterator if present.

Thomas



More information about the Python-list mailing list