5

appengine アプリケーションで、オブジェクトのリストのすべてのプロパティ名のセットを作成したいと考えています。これはかなり簡単です。

users = security.User.all().fetch(1000)
props = set([k for k in u.properties().keys() for u in users])

ただし、上記のコードはエラーになります。

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

デバッガーでいくつかの実験を行った後、ダミーの式を追加するとコードが修正されることに気付きました。

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])

これは私にとって非常に直感に反することですが、元のバージョンが Python 2.7 で失敗するのはなぜですか? そして、なぜ途中で「役に立たない」表現を追加すると問題が解決するのですか?

4

2 に答える 2

7

評価の順番を変えるだけ

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

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

また、リスト内包表記は必要ありませんが、セット内包表記を使用したジェネレーター式はここで機能します

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

評価の順番は右から左

あなたのオリジナル表現で

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

として壊すことができます

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

ダミー式を使用することの興味深い現象は、リスト内包表記が変数をリークするという事実でありu、グローバル スコープでリークが発生します。

そう

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

グローバルスコープでのリークu

作るもの

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

正当

次の例は、リスト内包表記が変数をリークする方法を示しています

>>> 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]
>>> 
于 2012-12-26T07:08:50.640 に答える