You can simplify arithmetic using
(n + 1)**2 == n**2 + (2*n + 1)
Here's how to do it using the generator function:
import math def squares(lo, hi): root = int(math.ceil(lo ** 0.5)) num = root ** 2 delta = 2 * root + 1 while num <= hi: yield num num += delta delta += 2 print list(squares(4, 16)) print list(squares(5, 50)) print list(squares(20, 90))
Output
[4, 9, 16] [9, 16, 25, 36, 49] [25, 36, 49, 64, 81]
Here is the equivalent iterator class. I gave it the __repr__ method, so it looks good if you print an instance of this class.
import math class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop root = int(math.ceil(start ** 0.5)) self.num = root ** 2 self.delta = 2 * root + 1 def __repr__(self): return 'Squares(%d, %d)' % (self.start, self.stop) def __iter__(self): return self def next(self): num = self.num if num > self.stop: raise StopIteration self.num += self.delta self.delta += 2 return num sq = Squares(4, 16) print sq for i in sq: print i print list(Squares(5, 50)) print list(Squares(20, 90))
Output
Squares(4, 16) 4 9 16 [9, 16, 25, 36, 49] [25, 36, 49, 64, 81]
For Python 3, replace the next method name with __next__ .
The usual Python range convention should stop before you reach the upper limit. To make this code consistent with this convention, in changing the squares() generator
while num <= hi:
to
while num < hi:
and in class squares() change
if num > self.stop:
to
if num >= self.stop: