On Saturday, March 22, 2014 8:11:27 AM UTC+5:30, Chris Angelico wrote: > On Sat, Mar 22, 2014 at 1:06 PM, Rustom Mody wrote: > > Two: A comprehension variable is not bound but reassigned across the > > comprehension. This problem remains in python3 and causes weird behavior > > when > > lambdas are put in a comprehension > >>>> fl = [lambda y : x+y for x in [1,2,3]] > >>>> [fl[i](2) for i in [0,1,2]] > > [5, 5, 5]
> To clarify, what you're saying here is that x in the first > comprehension's closures should be bound to separate values for x, > yes? Yes > I'm not sure how that ought to be done. Thats an implementation question -- see below. > Having closures that can > reference and modify each other's variables is important. Yes > def func_pair(): > x = 0 > def inc(): > nonlocal x; x+=1 > return x > def dec(): > nonlocal x; x-=1 > return x > return inc, dec > fooup, foodn = func_pair() > barup, bardn = func_pair() > >>> fooup(), fooup(), fooup(), foodn() > (1, 2, 3, 2) > >>> barup(), barup(), bardn(), bardn() > (1, 2, 1, 0) > Those functions are fundamentally linked. Very useful with callbacks. > A nice alternative to doing everything with bound methods. Yes > So if that's not going to be broken, how is this fundamentally different? > def func_loop(): > for x in 1,2,3: > yield (lambda: x) Thats using a for-loop A 'for' in a comprehension carries a different intention, the matching names being merely coincidental. This 'pun' causes cognitive dissonance in all these questions, including my gaffe above > one, two, three = func_loop() > one(), one(), two(), two(), three(), three() > This one does NOT work the way the names imply, and I can see that > you'd like to fix it. But I can't pinpoint a significant difference > between them. How do you distinguish? Using closures for carrying state is a different question As for comprehensions, the appropriate *intention* would be like this: Given fl = [lambda y : x+y for x in [1,2,3]] It means: def rec(l): if not l: return [] else: x,ll = l[0],l[1:] return [lambda y: x + y] + rec(ll) followed by fl = rec([1,2,3]) Naturally a reasonable *implementation* would carry this *intention* more efficiently with standard techniques like 1. Using list extend/append methods 2. Using lambda y, x=x: x+y Inside an implementation this is fine Forcing such tricks as kosher on a programmer is not (IMHO) [But then I find Lisp and much of basic haskell natural and most of C++ not, so my views are likely prejudiced :-) -- https://mail.python.org/mailman/listinfo/python-list