[Python-3000] Using *a for packing in lists and other places
Talin
talin at acm.org
Sun Mar 16 02:51:21 CET 2008
Guido van Rossum wrote:
> Also, yielding everything from an iterator:
>
>>>> def flatten(iterables):
> ... for it in iterables:
> ... yield *it
> ...
>>>> L = [ a, (3, 4), {5}, {6: None}, (i for i in range(7, 10)) ]
>>>> flatten(L)
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>
> What do people think?
(re-sending to the correct place - thanks Guido)
I've suggested something similar a while back:
http://mail.python.org/pipermail/python-list/2005-October/348485.html
At one point I was working on a algorithmic solver for mathematical
equations using recursive generators to do backtracking search; being
able to yield an entire generator's worth of output would have
simplified it considerably.
Also, there's a potential optimization - if a generator is yielding the
entire output of another generator, it might be possible to 'cut out the
middleman' and have the ultimate consumer of the values read the
innermost generator directly. I don't know how feasible that is, however.
All that being said: Using generators to implement backtracking search
is much nicer than trying to do it with regular recursion and callbacks;
But even nicer would be true coroutines.
Take for example the solver I mentioned, which basically is a unifier.
What it does is take two trees (composed of nested tuples) and
recursively walks them, matching as it goes. At each level, there may be
several possible ways of doing a match; The algorithm iterates through
each of these possibilities, invoking the lower-level matchers once for
each possibility. The lower-level matcher may in turn find several
possible matches, or may find none (meaning that the upper-level
possibility didn't pan out.)
When the algorithm gets to a leaf, it yields a result. The caller of the
algorithm receives essentially a stream of answers, which it can read as
many or as few as it wishes.
Since generators can't operate across multiple stack frames, the way to
construct this algorithm is to have each sub-matcher yield all of its
answers to its parent. This is where the 'yield *' syntax comes in.
In the case of the equation solver, the 'answers' consist of possible
variable bindings. So given the inputs 'x? + y?' and '1 + 2 + 3', the
stream of answers is (applying the associative rule):
(x = 1, y = 2 + 3)
(x = 1 + 2, y = 3)
...and so on
Now, one final comment: PEP 342 promises that the new yield semantics
can be used to implement true coroutines. But I don't see how to
actually make that work. Has anyone actually done this?
-- Talin
More information about the Python-3000
mailing list