Generators.
Lie Ryan
lie.1296 at gmail.com
Tue Dec 8 20:52:46 EST 2009
On 12/9/2009 3:52 AM, Jorge Cardona wrote:
> 2009/12/8 Lie Ryan<lie.1296 at gmail.com>:
>> First, I apologize for rearranging your message out of order.
>>
>> Theoretically yes, but the semantic of generators in python is they work on
>> an Iterable (i.e. objects that have __iter__), instead of a Sequence (i.e..
>> objects that have __getitem__). That means semantically, generators would
>> call obj.__iter__() and call the iter.__next__() and do its operation for
>> each items returned by the iterator's iterable's __next__().
>>
>> The lazy semantic would be hard to fit the current generator model without
>> changing the semantics of generator to require a Sequence that supports
>> indexing.
>>
>
> Why?
>
> The goal is add a formal way to separate the transformation of a
> generator in those that act on the indexing set and those that act on
> the result set.
<snip code>
Well, that's just a pretty convoluted way to reverse the order of the
operation (hey, why not reverse it altogether?). Nevertheless, it still
requires a semantic change in that all generators must be able to
produce the underlying stream, which is not always the case. Take this
small example:
def foo(x):
i = 0
while True:
yield i
i += 1
What would you propose the .indexing_set to be? Surely not the same as
.result_set? How would you propose to skip over and islice such
generator? without executing the in-betweens?
>> from functools import partial
>> def f(x):
>> print("eval: %d"%x)
>> return x
>>
>> X = range(10)
>> g = (partial(f, x) for x in X)
>>
>> print(list(x() for x in islice(g,0,None,2)))
>> # # or without partial:
>> # g = ((lambda: f(x)) for x in X)
>> # print(list(f() for f in islice(g,0,None,2)))
>>
>
> I keep here the problem in that i shouldn't be able to define the
> original generator because the function receive the already defined
> generator.
>
>> In a default-strict language, you have to explicitly say if you want lazy
>> execution.
>>
>>> What i want to do is a function that receive any kind of generator and
>>> execute it in several cores (after a fork) and return the data, so, i
>>> can't slice the set X before create the generator.
>>
>> beware that a generator's contract is to return a valid iterator *once*
>> only. You can use itertools.tee() to create more generators, but tee built a
>> list of the results internally.
>
> Oh, yes, i used tee first, but i note then that I wasn't using the
> same iterator in the same process, so, when the fork is made I can
> use the initial generator in different processes without this problem,
> so tee is not necessary in this case.
You would have to change tee as well:
>>> import itertools
>>> def foo(x):
... print('eval: %s' % x)
... return x + 1
...
>>> l = [1, 2, 3, 4, 5, 6, 7]
>>> it = iter(l)
>>> it = (foo(x) for x in it)
>>> a, b = itertools.tee(it)
>>> # now on to you
>>> it_a = itertools.islice(a, 0, None, 2)
>>> it_b = itertools.islice(b, 1, None, 2)
>>> next(it_b)
eval: 1
eval: 2
3
>>> next(it_b)
eval: 3
eval: 4
5
>>> next(it_b)
eval: 5
eval: 6
7
More information about the Python-list
mailing list