Conditionally implementing __iter__ in new style classes
Bengt Richter
bokr at oz.net
Wed Jul 6 13:03:04 EDT 2005
On Wed, 06 Jul 2005 17:57:42 +0200, Thomas Heller <theller at python.net> 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
More information about the Python-list
mailing list