
At 12:46 PM 10/17/03 -0700, Brett C. wrote:
Skip Montanaro wrote:
Is it supposed to return a generator function which I can assign to a variable (or pass to the builtin function sum() as in your example) and call later, or is it supposed to turn the current function into a generator function (so that each executed yield statement returns a value to the caller of the current function)?
It returns a generator function.
No, it returns an iterator. Technically a generator-iterator, but definitely not a generator function, just as [x for x in y] doesn't return a function that returns a list. :)
Personally I am not seeing any extreme need for this feature. I mean the example I keep seeing is ``sum((yield x*2 for x in foo))``. But how is this such a huge win over ``sum([x*2 for x in foo])``? I know there is a memory perk since the entire list won't be constructed, but unless there is a better reason I see abuse on the horizon.
It's not an extreme need; if it were, it'd have been added in 2.2, where all extreme Python needs were met. ;)
I know I am personally +0 on this even after my above worries since I don't see my above arguments are back-breakers and those of us who do know how to properly to use it will get a perk out of it.
I'm sort of +0 myself; there are probably few occasions where I'd use a gencomp. But I'm -1 on creating special indexing or listcomp-like accumulator syntax, so gencomps are a fallback position. I'm not sure gencomp is the right term for these things anyway... calling them iterator expressions probably makes more sense. Then there's not the confusion with generator functions, which get called. And this discussion has made it clearer that having 'yield' in the syntax is just plain wrong, because yield is a control flow statement. These things are really just expressions that act over iterators to return another iterator. In essence, an iterator expression is just syntax for imap and ifilter, in the same way that a listcomp is syntax for map and filter. Really, you could now write imap and ifilter as functions that compute iterator expressions, e.g.: imap = lambda func,items: func(item) for item in items ifilter = lambda func, items: item for item in items if func(item) Which of course means there'd be little need for imap and ifilter, just as there's now little need for map and filter. Anyway, if you look at '.. for .. in .. [if ..]' as a ternary or quaternary operator on an iterator (or iterable) that returns an iterator, it makes a lot more sense than thinking of it as having anything to do with generator(s). (Even if it might be implemented that way.)