class FibonacciIterator(object): def __init__(self, max_n): self._precalculated = {0: 1, 1: 1, 2: 2, 3: 3, 4: 5} self._biggest = 4 self._max_n = max_n self._i = 0 def get_biggest_pair(self): return ((self._biggest - 1, self._precalculated[self._biggest - 1]) , (self._biggest, self._precalculated[self._biggest])) def fibonacci_element(self, n): if(not isinstance(n, int)): raise TypeError("n must be integer") if(0 <= n <= self._biggest): return self._precalculated[n] (n_start_minus_one, b), (n_start, a) = self.get_biggest_pair() for i in range(n_start, n): swp = a a += b b = swp self._precalculated[n] = a self._biggest = n return a def __contains__(self, n): if(n > self._max_n): raise IndexError("{} > max_n({})".format(n, self._max_n)) return n <= self._biggest def __getitem__(self, n): if(n > self._max_n): raise IndexError("{} > max_n({})".format(n, self._max_n)) return self.fibonacci_element(n) def __iter__(self): self._i = -1 return self def __next__(self): if(self._i > self._max_n): raise StopIteration() self._i += 1 return self.fibonacci_element(self._i) if( __name__ == "__main__"): i = FibonacciIterator(20) for j in i: print(j) print(15 in i) print(i[14])