> >OK, I think I understand what you're after. The code for an iterator > >expression has to create a generator function behind the scenes, and > >call it. For example: > > > > A = (f(x) for x in S) > > > >could be translated into: > > > > def gen(seq): > > for x in seq: > > yield f(x) > > A = gen(S) > > > >(Note that S could be an arbitrary expression and should be evaluated > >only once. This translation does that correctly.) > > Interesting. That wasn't the semantics I envisioned. I was thinking > (implicitly, anyway) that an iterator comprehension was a closure. That > is, that S would be evaluated each time. We must be miscommunicating. In A = [f(x) for x in S] I certainly don't expect S to be evaluated more than once! Did you mean "each time through the loop" or "each time we reach this statement" or "each time someone loops over A" ??? Also note that I was giving the NON-reiterable semantics. I don't think there's any other way to do it (of course 'gen' should be an anonymous function). > However, if S is a sequence, you > don't need to reevaluate it, and if S is another iterator expression that > preserves reiterability, you still don't need to. So, in that sense > there's never a need to > > > >This allows one to iterate once over A (a generator function doesn't > >allow reiteration). What you are asking looks like it could be done > >like this (never mind the local names): > > Yes, that's actually what I said, but I guess I was once again unclear. > > > > def gen(seq): > > for x in seq: > > yield f(x) > > class Helper: > > def __init__(seq): > > self.seq = seq > > def __iter__(self): > > return gen(self.seq) > > A = Helper(S) > > > >Then every time you use iter(A) gen() will be called with the saved > >value of S as argument. > > Yes, except of course Helper would be a builtin type. Sure, and its constructor would take 'gen' as an argument: class Helper: def __iter__(self, seq, gen): self.seq = seq self.gen = gen def __iter__(self): return self.gen(self.seq) def gen(seq): for x in seq: yield f(x) A = Helper(S, gen) > >I don't mind that so much, but I don't think all the extra machinery > >is worth it; the compiler generally can't tell if it is needed so it > >has to produce the reiterable code every time. > > It has to produce the generator every time, anyway, presumably as a > nested function with access to the current locals. The only > question is whether it can be invoked more than once, and whether > you create the helper object. But maybe that's what you mean, and > now you're being unclear instead of me. ;) I meant creation of the Helper instance. Given that in most practical situations if you *need* reiterability you can provide it using something much simpler, I don't like using a Helper instance. But in fact I don't even like having the implicit generator function. I guess that's one reason I'm falling down on the -0 side of this anyway... > > If you *want* to > >have an iterable instead of an iterator, it's usually easy enough do > >(especially given knowledge about the type of S). > > I just tend to wish that I didn't have to think about whether > iterators are reiterable or not, as it forces me to expose to > callers of a function whether the value they pass must be an > iterator or an iterable. To me that's a perfectly reasonable requirement, as long as functions taking an iterator also take an iterable (i.e. they call iter() on their argument), so a caller who has only iterables doesn't have to care about the difference. --Guido van Rossum (home page: http://www.python.org/~guido/)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4