Fibonacci Iterator

Write an iterator that gives back all the Fibonacci numbers up to a given value.
Use it to get the highest Fibonacci number less than 1000, and to check which if there is in that range a multiple of 12.

This problem is thought as a follow-up to the previous post, where we implemented the same functionality as a Python generator. I have extracted it from Dive into Python 3, section 7.5. The idea is showing how python generators are shortcut implementation of iterators.
class Fibonacci:
    def __init__(self, top):  # 1
        self.top = top

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

    def __next__(self):  # 3
        if self.a > self.top:
            raise StopIteration  # 4

        result = self.a
        self.a, self.b = self.b, self.a + self.b
        return result
1. Initialize a Fibonacci object setting its top value.
2. The special __iter__() method prepares a Fibonacci object to be used as an iterator.
3. Each call to a Fibonacci object as iterator resolves to a call to its special method __next__()
4. The end of iterations is signaled raising a StopIteration exception. So, in this context an exception is not exceptional at all.

Even though the implementation is much verbose, in this case the functionality is just the same. So, beside studying purpose, the generator version easily wins over this iterator one.

The user is minimally affected by the implementation change, as you can see in these tests:
def test_list_1000(self):
    fib1000 = list(Fibonacci(1000))
    self.assertEqual(17, len(fib1000))
    self.assertEqual(987, fib1000[-1])

def test_multiple_12(self):
    for candidate in Fibonacci(1000):
        if candidate and candidate % 12 == 0:
            break
    else:
        self.fail('No fibonacci multiple of 12 found!')
    self.assertEqual(144, candidate)
If you want, you could check the full code on GitHub.

No comments:

Post a Comment