Welcome to the wonderful flow control world. Python 2.2 (now the third edition of the Alpha release-see resources later in this article) will give programmers some new options that are not available in earlier Python versions--or at least not very convenient.
While the Python 2.2 gives us less understanding than complete continuity and stackless in Python, it can be said that the behavior of generators and iterators is somewhat different from traditional functions and classes.
Since the iterator is easier to understand, let's look at it first. Essentially, an iterator is an object that contains a. Next () method. Well, that's not exactly the right definition, but it's very close. In fact, when the iterator applies the new ITER () built-in function, the context of most iterators wants an object that can generate an iterator. To make the user-defined class (which contains an essential. Next () method) return an iterator, you need to make the __iter__ () method return self. The example in this article clearly illustrates this point. If an iteration has a logical termination, the. Next () method of the iterator may decide to throw a stopiteration exception.
The builder is slightly more complex and a little more generalized. But the most typical use of generators is to define iterators, so it's not always worth worrying about the nuances. The builder is a function that remembers the position of the last time it was returned in the body of the function. The second (or nth) call to the generator function jumps to the middle of the function, and all local variables that were last called remain unchanged.
In some ways, the builder is like "terminate" in functional programming discussed in the previous article in this column (see Resources). Like "Terminate", the generator "remembers" its data state. But the builder goes a step further than "terminate": The generator also "remembers" its position in the flow control construct (in imperative programming, this construct is not just a data value). Because continuity allows you to perform any jumps between frames, rather than always returning to the immediate caller's context (as the builder does), it is still relatively generic.
Fortunately, it is much easier to use a builder than to understand all the conceptual issues of program flow and state. In fact, after a little practice, you can use the builder as easily as a normal function.
Random traversal
Let's consider a fairly simple question that can be solved in a number of ways--both new and old methods. Suppose we want a stream of positive random numbers, which is smaller than a digital stream that obeys a backward reference constraint. Specifically, we want each subsequent number to be at least 0.4 larger or smaller than the previous one. Moreover, the digital stream itself is not infinite and ends after several random steps. In this example, when a number less than 0.1 is generated in the digital stream, we will simply end it. The above constraint is somewhat like a constraint that can be found in a "random traversal" algorithm, where the end condition resembles a "statistic" or "local minimum" result--but of course, this is simpler than most real world.
In Python version 2.1 or earlier, there are several ways to solve this problem. One way is to simply generate a list of numbers in the stream and return it. May look like this:
randomwalk_list.py
import
random
def
randomwalk_list
():
last, rand = 1, random.random()
# init candidate elements
nums = []
# empty list
while
rand > 0.1:
# threshhold terminator
if
abs(last-rand) >= 0.4:
# accept the number
last = rand
nums.append(rand)
# add latest candidate to nums
else
:
print
'*',
# display the rejection
rand = random.random()
# new candidate
nums.append(rand)
# add the final small element
return
nums