Using nested generator expression in Python 2.7

google-app-engine, python

Solution

Just change the order of evaluation

props = set([k for k in u.properties().keys() for u in users])

to

props = set([k for u in users for k in u.properties().keys() ])

also you don't need a list comprehension but generator expression with a set comprehension would work here

props = set(k for u in users for k in u.properties().keys() )

Order of evaluation is from right to left

In your original expression

set([k for k in u.properties().keys() for u in users])

can be broken as

for k in u.properties().keys(): # Here u is undefined
    for u in users:
        #what ever

The interesting phenomena of using a Dummy expression is the fact that List Comprehension Leaks Variables, which causes `u` to be leaked in the global scope

So

[u.properties().keys() for u in users]

leaks `u` in global scope,

which makes

set([k for k in u.properties().keys() for u in users])

legitimate

The following example shows, how list comprehension leaks variables

>>> del i
>>> foo = [range(1,10) for _ in range(10)]
>>> globals()['i']

Traceback (most recent call last):
  File "<pyshell#84>", line 1, in <module>
    globals()['i']
KeyError: 'i'
>>> [i for i in foo]
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9]]
>>> globals()['i']
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 

Problem

In an appengine application, I want to build a set of all property names for a list of objects. This should be fairly straightforward: ``` users = security.User.all().fetch(1000) props = set([k for k in u.properties().keys() for u in users]) ``` However, the code above results in an error: ``` File "/Users/paulkorzhyk/Projects/appengine-flask-template/app/app.py", line 70, in allusers props = set([k for k in u.properties().keys() for u in users]) UnboundLocalError: local variable 'u' referenced before assignment ``` After some experiments in the debugger I've noticed that adding a dummy expression fixes the code: ``` users = security.User.all().fetch(1000) [u.properties().keys() for u in users] props = set([k for k in u.properties().keys() for u in users]) ``` This is quite counter-intuitive to me, why is original version failing in Python 2.7? and why adding a 'useless' expression in the middle fixes the problem?

Original source

Related problems