From: Alain Ketterlin on 6 Apr 2010 04:51 Steven D'Aprano writes: >> d = dict() >> for r in [1,2,3]: >> d[r] = [r for r in [4,5,6]] >> print d > > This isn't directly relevant to your problem, but why use a list > comprehension in the first place? [r for r in [4,5,6]] is just [4,5,6], > only slower. Sure. But I've actually spent some time reducing the real code to a simple illustration of the problem. >> THe problem is that the "r" in d[r] somehow captures the value of the >> "r" in the list comprehension, and somehow kills the loop interator. The >> (unexpected) result is {6: [4, 5, 6]}. > > Actually, no it doesn't kill the loop at all. You have misinterpreted > what you have seen: It kills the iterator, not the loop. Sorry, I used 'kill' with the meaning it has in compiler textbooks: to assign a new value to a variable. > It is expected, because list comprehensions leak the variable into the > enclosing scope. Thanks. -- Alain. From: Lie Ryan on 6 Apr 2010 12:34 On 04/06/10 18:42, Alain Ketterlin wrote:> Alain Ketterlin writes: > >> d = dict() >> for r in [1,2,3]: >> d[r] = [r for r in [4,5,6]] >> print d > > Thanks to Chris and Paul for the details (the list comp. r actually > leaks). I should have found this by myself. > > My background is more on functional programming languages, that's why I > thought the list comprehension iterator should be purely local. And yes, > I think a "classical" for-loop iterator should also be local to the > loop, but I understand this may be too counter-intuitive to many :-) Actually in other programming languages, loop counter is usually local: for (int i = 0; i < something; i++) { .... } foo(i); // illegal The reason why python's loop counter leaks is for implementation simplicity because otherwise python will have to deal with multi-layered local namespace. Currently in python, the local namespace is just sugar for an array access (a bit of hand-waving here). In other languages, a {} block is a namespace and nested {} block means nested namespace even if they're still in a single function; in python there is only a flat local namespace and the names resolver becomes a thousand times simpler (and faster). From: Stephen Hansen on 6 Apr 2010 12:34 On 2010-04-06 09:34:04 -0700, Lie Ryan said:> in python there is only a flat > local namespace and the names resolver becomes a thousand times simpler > (and faster). This hasn't been true for a long time. Yes, local variables are optimized to be indexed in an array, but Python has nested scopes for functions. But it does not have true lexical scoping, no. -- --S .... p.s: change the ".invalid" to ".com" in email address to reply privately. From: Gregory Ewing on 6 Apr 2010 19:13 Lie Ryan wrote:> in python there is only a flat > local namespace and the names resolver becomes a thousand times simpler No, it doesn't. The compiler already has to deal with multiple scopes for nested functions. There may be some simplification, but not a lot. The main reason is linguistic. Having nested blocks create new scopes does not fit well with lack of variable declarations. -- Greg From: Rolando Espinoza La Fuente on 6 Apr 2010 19:58 On Sun, Apr 4, 2010 at 5:20 PM, Paul Rubin wrote: [...]> > Â  Â d[r] = list(r for r in [4,5,6]) > This have a slightly performance difference. I think mainly the generator's next() call. In [1]: %timeit list(r for r in range(10000)) 100 loops, best of 3: 2.78 ms per loop In [2]: %timeit [r for r in range(10000)] 100 loops, best of 3: 1.93 ms per loop ~Rolando