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 result1. 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.