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.
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()
                        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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With