"James Stroud" <[EMAIL PROTECTED]> wrote in message 
news:[EMAIL PROTECTED]
| Beorn wrote:
| > Consider this example:
| >
| >   >>> def funcs(x):
| >   ...     for i in range(5):
| >   ...         def g(): return x + i
| >   ...         yield g
| >
| >   >>> [ fun() for fun in list(funcs(1)) ]
| >   [5, 5, 5, 5, 5]
| >
| > Whereas:
| >
| >   >>> [ fun() for fun in funcs(1) ]
| >   [1, 2, 3, 4, 5]

| If this isn't classified as a bug,

It is not, it is well-documented behavior.  Still, suggestions for 
improvement might be considered.

| Why would it be desirable for a generator to behave
| differently in two different contexts.

I have no idea.

Each call of the generator function funcs behaves the same.  It returns a 
generator that yields 5 identical copies of the inner function g.  The 
multiple copies are not needed and only serve to confuse the issue. 
Changing funcs to return a generator that yields the *same* function (five 
times) gives the same behavior.

def funcs(x):
    def g(): return x + i
    for i in range(5):
        yield g

print [ fun() for fun in list(funcs(1)) ]
print [ fun() for fun in funcs(1) ]

>>> # when run
[5, 5, 5, 5, 5]
[1, 2, 3, 4, 5]

What matters is the value of g's nonlocal var i (funcs' local var i) when 
the yielded function g is *called*.

The difference between returning versus yielding an inner closure such as g 
is this.  If g is returned, the outer function has terminated and the 
enclosed variable(s), i in this case, is frozen at its final value.  If g 
is yielded, the enclosed i is *live* as long as the generator is, and its 
values can change between calls, as in the second print statement.

| Should I import this to see how
| many principles this behavior violates?

???

If you meant 'report' (on SF), please do not.

Terry Jan Reedy



-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to