Checking if an object is iterable is correctly, as you've done, performed with:
isinstance(obj, collections.Iterable)
The problem here is you're supplying a class
to isinstance
and not an instance. It is False
because isinstance
will go ahead and check if type(fib)
has an __iter__
method defined:
type(fib).__iter__ # AttributeError
This of course, isn't the case. type(fib)
is type
which doesn't define an __iter__
method.
If you supply an instance to it, it correctly prints True
:
isinstance(fib(), Iterable) # True
because looking in type(fib())
it will find fib.__iter__
.
Alternatively, feeding fib
to issubclass
performs a similar check that, instead, takes a class as a first argument:
issubclass(fib, Iterable) # True
Two extra minor things to point out:
- Using
object
as an explicit base class is unnecessary in Python 3
(though, if you're developing code that runs on both Py2 and Py3, it is a good thing. (See Python class inherits object for more on this.)
- According to PEP 8, class names should follow the CapWords convention, so
fib
should ideally be named Fib
.