Python defining an iterator class, failed with "iter() returned non-iterator of type 'Fib'"

22,519

Solution 1

def __next__(self) is for Python 3

For Python 2 you need to add method next()

This code will work under both Python 3 and Python 2:

class Fib(object):
    def __init__(self, max):
        super(Fib, self).__init__()
        self.max = max

    def __iter__(self):
        self.a = 0
        self.b = 1
        return self

    def __next__(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

    def next(self):
        return self.__next__()


def main():
    fib = Fib(100)
    for i in fib:
        print(i)

if __name__ == '__main__':
    main()

Solution 2

That's python 3 code where the iterator protocol uses the __next__ method. The best fix is to start using python 3. But if you need python 2, just change __next__ to next. The reason for the change was to make sure magic methods such as next conform to the __ naming convention.

Share:
22,519

Related videos on Youtube

Troskyvs
Author by

Troskyvs

Updated on December 02, 2020

Comments

  • Troskyvs
    Troskyvs over 3 years

    I'm using python 2.7 and ipython2.7. In ipython I tried:

    class Fib(object):
        def __init__(self, max):
            super(Fib, self).__init__()
            self.max = max
    
        def __iter__(self):
            self.a = 0
            self.b = 1
            return self
    
        def __next__(self):
            fib = self.a
            if fib > self.max:
                raise StopIteration
            self.a, self.b = self.b, self.a + self.b
            return fib
    
    def main():
        fib = Fib(100)
        for i in fib:
            print i
    
    if __name__ == '__main__':
        main()
    

    Well it reports an error:

    TypeError Traceback (most recent call last) in () 22 23 if name == 'main': ---> 24 main() 25

    <ipython-input-21-f10bd2d06666> in main()
        18 def main():
        19     fib = Fib(100)
    ---> 20     for i in fib:
        21         print i
        22
    
    TypeError: iter() returned non-iterator of type 'Fib'
    

    This piece of code is actually from internet. The gramma seems OK to me, but how the problem happens?

    Thanks.

    • user3030010
      user3030010 over 7 years
      It runs fine in Python 3. You'll either have to start using Python 3, or update the code to work with Python 2.
    • Troskyvs
      Troskyvs over 7 years
      I know now, that __next__() is for Python3 and next() is for python 2.7. This is so tricky!