[Python-Dev] code blocks using 'for' loops and generators

Brian Sabbey sabbey at u.washington.edu
Sun Mar 13 00:54:10 CET 2005


On Sat, 12 Mar 2005, Josiah Carlson wrote:

> I say it is magical.  Why?  The way you propose it, 'yield' becomes an
> infix operator, with the name provided on the left being assigned a
> value produced by something that isn't explicitly called, referenced, or
> otherwise, by the right.  In fact, I would say, it would be akin to the
> calling code modifying gen.gi_frame._f_locals directly.  Such "action at
> a distance", from what I understand, is wholly frowned upon in Python.
> There also does not exist any other infix operator that does such a
> thing (=, +=, ... assign values, but where the data comes from is
> obvious).
>
> Bad things to me (so far):
> 1. Assignment is not obvious.
> 2. Where data comes from is not obvious.
> 3. Action at a distance like nothing else in Python.
> 4. No non-'=' operator assigns to a local namespace.

If it is too much action at a distance, one could also use the syntax "a = 
yield b", as has been suggested before, but I preferred it without the 
'='.  With the '=', I don't see how it is any more action at a distance 
than "a = yield_func(b)" or "for i in f()".  In all of these cases, values 
are being passed when the scope is changing.

If you want to argue that both of these syntaxes are too ugly to be 
allowed, then ok.

> Or you could even use a class instance.
>
> class foo:
>    def pickled_file(self, name):
>        f = open(name, 'r')
>        yield pickle.load(f)
>        f.close()
>        f = open(name, 'w')
>        pickle.dump(self.l, f)
>        f.close()
>
> fi = foo()
> for l in fi.pickled_file('greetings.pickle'):
>     l.append('hello')
>     l.append('howdy')
>     fi.l = l
>
> If you can call the function, there is always a shared namespace.  It
> may not be obvious (you may need to place the function as a method of an
> instance), but it is still there.

The disadvantage of this method is that it is not clear where the self.l 
values is coming from just by reading the generator method definition. If 
it is coming from the code block, why not be able to explicity write it 
that way?  Similarly, "continue l" explicitly shows that you are passing a 
value back to the generator.

>>> Hrm, not good enough?  Use a Queue, or use another variable in a
>>> namespace accessable to both your function and your loop.
>>
>> Again, I entirely realize it's possible to do these things now, but that
>> is not the point.
>
> The point of your proposed syntax is to inject data back into a
> generator from an external namespace.  Right?

The point is to inject data back into a generator in a clean, explicit 
way;  I understand there are other ways in which one can already do this.

> Furthermore, I would say that using yield semantics in the way that you
> are proposing, while being discussed in other locations (the IBM article
> on cooperative multithreading via generators springs to mind), is a
> clever hack, but not something that should be supported via syntax.

My impression is that being able to use yield in this way is one of the 
primary reasons for the success of ruby.  Therefore, I do not see it as 
just a clever hack.  It is a clean, explicity way to pass values when 
changing scope.

-Brian


More information about the Python-Dev mailing list