4

exec と eval での辞書内包表記と他のメソッドの使用には、次の違いがあることがわかりました。要約すると、違いは、内包表記を使用する場合、変数は globals 引数から取得されますが、内包表記を使用しない同等のコードは locals 引数から変数を取得することです。

これは、Python Software Foundation Windows インストーラーの Python 2.7.3 で見つかりました。

次のコードを実行する場合:

locals1 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
globals1 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
exec "new = {key:d[key] for key in d if key != test}" in globals1, locals1
print locals1

出力は次のとおりです。

{'test': 3, 'new': {1: 'a', 3: 'c'}, 'd': {1: 'x', 2: 'y', 3: 'z'}}

辞書 (d) とテスト値 (test) は両方とも globals 引数から取得されることに注意してください。

同等のコードが実行されると:

locals2 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
globals2 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
exec "new = d.copy(); new.pop(test)" in globals2, locals2
print locals2

次の出力が生成されます。

{'test': 3, 'new': {1: 'x', 2: 'y'}, 'd': {1: 'x', 2: 'y', 3: 'z'}}

この場合、辞書 (d) とテスト値 (test) は両方とも locals 引数から取得されます。

さらに、ディクショナリおよび/またはテスト値がローカル引数にある場合でも、グローバル引数にない場合、内包表記を使用したコードの実行は変数が見つからないという例外で失敗することを示しています。

これは exec の使用に関する質問ではないことに注意してください。私が exec を使用するのには十分な理由があります。eval を使用して同じ状況を示すことができます。

4

1 に答える 1

1

これは完全に正しいです。辞書内包表記は関数スコープとして実行されます。そのスコープで定義されていない関数スコープで参照されるすべての変数は、グローバルであると見なされます。

exec-ed コードで明示的な関数を使用すると、同じ効果が得られます。

>>> locals3 = {"d":{1: 'x', 2: 'y', 3: 'z'}, "test":3}
>>> globals3 = dict(globals().items() + [("d", {1: 'a', 2: 'b', 3: 'c'}), ("test", 2)])
>>> exec "def f():\n    new = d.copy()\n    new.pop(test)\n    return new\nnew = f()" in globals3, locals3
>>> print locals3
{'test': 3, 'new': {1: 'a', 3: 'c'}, 'd': {1: 'x', 2: 'y', 3: 'z'}, 'f': <function f at 0x106bbcaa0>}

これは、セットと辞書の表示セクションに記載されています。

内包表記は別のスコープで実行されるため、ターゲット リストで割り当てられた名前が外側のスコープで「リーク」しないことに注意してください。

Python 2.x では、リスト内包表記は独自のスコープを取得しません。これは Python 3 で変更されています。

于 2013-08-03T21:47:20.600 に答える