[puzzle]

Terry Reedy tjreedy at udel.edu
Mon Dec 29 06:02:30 CET 2003

"Anton Vredegoor" <anton at vredegoor.doge.nl> wrote in message
I don't know what 'Glen Wheeler's problem' is, what your 'antonian' numbers
are, what 'ISTMT' abbreviates, nor precisely what 'sorted reflected' means
to your without an example, so I won't try to solve your puzzle.  I will
just comment on the class definition.

> class AntonianSorted:
>
>     def __init__(self, n, k):
>         self.limits = [k for i in range(n)]
>         self.state = []
>         self.iterator = self.__gen__()
>
>     def __iter__(self):  return self
>     def next(self):  return self.iterator.next()

The generation will go faster if you delete the above three line and change
'gen' to 'iter' in the next.

>     def __gen__(self):
>         state, limits = self.state, self.limits
>         while 1:
>             if len(state) < len(limits):
>                 state.append(0)
>             else:
>                 i = len(state)-1
>                 while i > 0 and state[i] == limits[i]-1:
>                     state.pop()
>                     i -= 1
>                 if state[i] < limits[i]-1:
>                     state[i] += 1
>                 else:
>                     raise StopIteration
>             yield state[:]

Making __iter__ itself a generator function (which returns an iterator, as
__iter__ should) is the smoothest way to use generators with classes.
Wrapping genit.next with a regular function undoes perhaps half the speed
benefit of generators.  They are fast partly because they do not have to
stash and retrieve local in the instance and partly because they resume
without the normal (slow) function call process.  Writing __iter__ as
generator also make the instance reiterable.

In this case, I do not see any reason to wrap the generator in a class
instead of calling it directly, but perhaps you have a usage in mind where
persisting the instance after the generator run makes sense.

Terry J. Reedy