In [5]:
# the last way to write generators is to implement a class with the appropriate
# special methods.

# if you implement __iter__ to return an iterator, objects of your class
# become iterable.

class MyRange(object):
    def __init__(self, n):
        self.n = n
        self.i = 0
    def __iter__(self):
        return self
    def next(self):
        if self.i >= self.n:
            raise StopIteration
        ret = self.i
        self.i += 1
        return ret
    
for n in MyRange(5):
    print n


0
1
2
3
4

In [8]:
# you do not have to return "self" from iterator to make an object
# iterable; you can return any iterator you want

class PhoneNumber(object):
    def __init__(self, area, exchange, number):
        self.area = area
        self.exchange = exchange
        self.number = number
    def __iter__(self):
        def digits():
            for d in '%03d%03d%04d' % (self.area, self.exchange, self.number):
                yield d
        return digits()
    
for d in PhoneNumber(800, 555, 1212):
    print d


8
0
0
5
5
5
1
2
1
2