# iterable class
class naturals(object):
def __init__(self, top):
assert top >= 1, 'top >= 1'
self._cur = 1
self._top = top
def __iter__(self):
return self
def __next__(self):
if self._cur > self._top:
raise StopIteration()
tmp = self._cur
self._cur += 1
return tmp
# generator function
def naturals(top):
n = 1
while n <= top:
# `yield x` puts the value `x` on hold, and halts function execution.
# the result is a generator object, which follows the iterator pattern.
# calling next() on one of these will return `x` and resume function
# execution, until another `yield` statement is found or the function ends
yield n
n += 1
# for-in iteration
for n in naturals(10):
print(n)
# manual iteration (naive, imho)
it = naturals(10)
try:
while True:
n = next(it)
print (n)
except StopIteration:
pass
# manual iteration (generic)
nums = naturals(10)
it = iter(nums) # make sure we are dealing with an iterator object
sentinel = object() # create unique object
while True:
n = next(it, sentinel) # next returns sentinel instead of raising exception
if n is sentinel:
break
print(n)