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.
source to share
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.
source to share