First I want to clarify, I'm NOT asking what is "iterator".
This is how the term "iterable" is defined in Python's doc:
iterable
An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects, and objects of any classes you define with an __iter__() or __getitem__() method.
Iterables can be used in a for loop and in many other places where a sequence is needed (zip(), map(), ...). When an iterable object is passed as an argument to the built-in function iter(), it returns an iterator for the object. This iterator is good for one pass over the set of values. When using iterables, it is usually not necessary to call iter() or deal with iterator objects yourself. The for statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop.
See also iterator, sequence, and generator.
As other people suggested, using isinstance(e, collections.Iterable)
is the most pythonic way to check if an object is iterable.
So I did some test with Python 3.4.3:
from collections.abc import Iterable
class MyTrain:
def __getitem__(self, index):
if index > 3:
raise IndexError("that's enough!")
return index
for name in MyTrain():
print(name) # 0, 1, 2, 3
print(isinstance(MyTrain(), Iterable)) # False
The result is quite strange: MyTrain
has defined __getitem__
method, but it is not considered as an iterable object, not to mention it's capable of returning one number at a time.
Then I removed __getitem__
and added the __iter__
method:
from collections.abc import Iterable
class MyTrain:
def __iter__(self):
print("__iter__ called")
pass
print(isinstance(MyTrain(), Iterable)) # True
for name in MyTrain():
print(name) # TypeError: iter() returned non-iterator of type 'NoneType'
It is now considered as a "true" iterable object in spite of it cannot produce anything while iterating.
So did I misunderstand something or is the documentation incorrect?