Why isn't an object that implements __iter__ recognized as iterable?

Let's say you are working with a wrapper object:

class IterOrNotIter:
    def __init__(self):
        self.f = open('/tmp/toto.txt')
    def __getattr__(self, item):
        try:
            return self.__getattribute__(item)
        except AttributeError:
            return self.f.__getattribute__(item)

      

This object implements __iter__

because it passes any call to its member f

that implements it. Example:

>>> x = IterOrNotIter()
>>> x.__iter__().__next__()
'Whatever was in /tmp/toto.txt\n'

      

According to the documentation ( https://docs.python.org/3/library/stdtypes.html#iterator-types ), IterOrNotIter should be iterable this way.

However, the Python interpreter does not recognize the object IterOrNotIter

, as it is indeed iterable:

>>> x = IterOrNotIter()
>>> for l in x:
...    print(l)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'IterOrNotIter' object is not iterable

      

Whereas this works:

>>> x = IterOrNotIter()
>>> for l in x.f:
...    print(l)
...
Whatever was in /tmp/toto.txt

      

I do not understand why.

+3


source to share


1 answer


Mainly because your class just doesn't have a real method __iter__

:

>>> hasattr(IterOrNotIter, '__iter__')
False

      

Thus, it does not qualify as an iterator, because the actual check for __iter__

tests for existence, rather than assuming an implementation. So the workarounds with __getattr__

or __getattribute__

(unfortunately) don't work.

This is actually mentioned in the documentation for __getattribute__

:



Note

This method can still be bypassed when looking for special methods as a result of implicit invocation through language syntax or built-in functions. See Ad hoc method search .

The last section also explains why :

Bypassing the technique __getattribute__()

in this way provides significant opportunities for optimizing speed in the interpreter at the expense of some flexibility in handling special methods (a special method must be set on the class object itself in order to be called sequentially by the interpreter ).

Emphasis on mine.

+2


source







All Articles