次のコードは、_Python2
_と_Python3
_で異なる出力を提供します。
_from sys import version
print(version)
def execute(a, st):
b = 42
exec("b = {}\nprint('b:', b)".format(st))
print(b)
a = 1.
execute(a, "1.E6*a")
_
_Python2
_の出力:
_2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]
('b:', 1000000.0)
1000000.0
_
_Python3
_の出力:
_3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
_
なぜ_Python2
_はb
関数内の変数execute
をexec
関数の文字列の値にバインドしますが、_Python3
_はバインドしませんこれを行う? _Python2
_で_Python3
_の動作を実現するにはどうすればよいですか?私はすでに_Python3
_のexec
関数にグローバルとローカルの辞書を渡そうとしましたが、今のところ何もうまくいきませんでした。
---編集---
Martijnsの回答を読んだ後、_Python3
_でこれをさらに分析しました。次の例では、locals()
辞書をd
としてexec
に指定していますが、_d['b']
_はb
を印刷する以外の何かを印刷します。
_from sys import version
print(version)
def execute(a, st):
b = 42
d = locals()
exec("b = {}\nprint('b:', b)".format(st), globals(), d)
print(b) # This prints 42
print(d['b']) # This prints 1000000.0
print(id(d) == id(locals())) # This prints True
a = 1.
execute(a, "1.E6*a")
3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
1000000.0
True
_
d
とlocals()
のIDの比較は、それらが同じオブジェクトであることを示しています。ただし、これらの条件下では、b
は_d['b']
_と同じである必要があります。私の例では何が間違っていますか?
exec
in Python 2とexec()
in Python 3)には大きな違いがあります。exec
関数としてですが、実際にはPython 2.のstatement)です.
この違いのため、Python 2.で可能であったとしても、exec
を使用してPython 3で関数スコープのローカル変数を変更することはできません。以前に宣言された変数でさえありません。
locals()
は、一方向のローカル変数のみを反映します。以下は2でも3でも機能しませんでした。
_def foo():
a = 'spam'
locals()['a'] = 'ham'
print(a) # prints 'spam'
_
Python 2、exec
ステートメントを使用すると、コンパイラはローカルスコープの最適化をオフにすることを知っていました(たとえば、_LOAD_FAST
_から_LOAD_NAME
_への切り替え)ローカルスコープとグローバルスコープの両方で変数を検索します)exec()
が関数である場合、そのオプションは使用できなくなり、関数スコープは現在always最適化されています。
さらに、Python 2、exec
ステートメントは、locals()
で見つかったすべての変数を_PyFrame_LocalsToFast
_を使用して関数localsに明示的にコピーします。ただし、 globalsおよびlocalsパラメーターは指定されていません。
適切な回避策は、exec()
呼び出しに新しい名前空間(辞書)を使用することです。
_def execute(a, st):
namespace = {}
exec("b = {}\nprint('b:', b)".format(st), namespace)
print(namespace['b'])
_
exec()
documentation は、この制限について非常に明示的です:
注:デフォルトのlocalsは、以下の関数
locals()
の説明に従って動作します。デフォルトlocalsディクショナリにしようとしないでください。関数exec()
が戻った後にローカルのコードの効果を確認する必要がある場合は、明示的なlocals辞書を渡します。
Python3のバグだと思います。
_def u():
exec("a=2")
print(locals()['a'])
u()
_
「2」を出力します。
_def u():
exec("a=2")
a=2
print(a)
u()
_
「2」を出力します。
だが
_def u():
exec("a=2")
print(locals()['a'])
a=2
u()
_
失敗する
_Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in u
KeyError: 'a'
_
---編集---もう一つの興味深い振る舞い:
_def u():
a=1
l=locals()
exec("a=2")
print(l)
u()
def u():
a=1
l=locals()
exec("a=2")
locals()
print(l)
u()
_
出力
_{'l': {...}, 'a': 2}
{'l': {...}, 'a': 1}
_
そしてまた
_def u():
l=locals()
exec("a=2")
print(l)
print(locals())
u()
def u():
l=locals()
exec("a=2")
print(l)
print(locals())
a=1
u()
_
出力
_{'l': {...}, 'a': 2}
{'l': {...}, 'a': 2}
{'l': {...}, 'a': 2}
{'l': {...}}
_
どうやら、ローカルでのexec
のアクションは次のとおりです。
exec
内で設定され、この変数がローカル変数であった場合、exec
は内部辞書(locals()
によって返されるもの)を変更し、それを返しません。元の状態。 locals()
を呼び出すと、辞書が更新され(python documentation)のセクション2で説明されているように)、exec
内に設定された値が忘れられます。 locals()
を呼び出して辞書を更新することは、ドキュメント化されているためpython3のバグではありませんが、直観的ではありません。また、exec
内のローカルの変更は関数のローカルはpython2との文書化された違いです(ドキュメントでは「関数exec()が戻った後にローカルのコードの効果を確認する必要がある場合は明示的なローカル辞書を渡す」と書かれています)。exec
内に設定され、この変数が以前に存在しなかった場合、exec
は、後で変数が設定されない限り、内部辞書を変更します。 locals()
が辞書を更新する方法にバグがあるようです。このバグは、exec
の後にlocals()
を呼び出すことにより、exec
内で設定された値にアクセスできます。まとめると:
exec
の異なる動作は、Python 2のステートメントであるexec
に由来しますが、Python 3。ご注意ください:
ここで新しいことは何も伝えません。これは、他のすべての回答とコメントにある真実の集合体です。私がここで試みるのは、より曖昧な詳細のいくつかに光を当てることです。
Python 2とPython 3の唯一の違いは、実際にexec
は囲んでいる関数のローカルスコープを変更できることです。 in Python 2(ステートメントであり、現在のローカルスコープにアクセスできるため)およびin Python 3(現在は関数であるため) 、したがって、独自のローカルスコープで実行されます)。
ただし、刺激はexec
ステートメントとは関係なく、1つの特別な動作の詳細にのみ起因します。
locals()
は何かを返します。これを「locals()
の呼び出し後、常にローカルスコープ内のすべての変数のみを参照するスコープごとに変更可能なシングルトン」と呼びます。
locals()
の動作は、Python 2と3の間で変化しなかったことに注意してください。したがって、この動作はexec
の動作方法の変更とともに不安定ですが、常にそこにあった詳細を公開するだけではありません。
「ローカルスコープ内の変数を参照するスコープごとの可変シングルトン」とはどういう意味ですか?
scope-wise singleton
_です。同じスコープ内でlocals()
を呼び出す頻度に関係なく、返されるオブジェクトは常に同じです。id(d) == id(locals())
という観察は、d
とlocals()
が同じオブジェクト、同じシングルトンを参照しているためです。別のオブジェクトを取得しますが、同じスコープではこの単一のオブジェクトのみが表示されます)。mutable
であるため、変更できます。locals()
は、オブジェクト内のすべてのエントリがローカルスコープ内の変数を再度参照するように強制します。d
を介して)変更すると、通常の変更可能なオブジェクトであるため、これによりオブジェクトが変更されます。オブジェクトのすべてのエントリは_references to the variables in the local scope
_であるため、シングルトンのこれらの変更はローカルスコープに反映されません。したがって、エントリを変更すると、これらはシングルトンオブジェクトを変更し、「参照を変更する前に参照が指していた場所」の内容は変更しません(したがって、ローカル変数は変更しません)。
Pythonでは、文字列と数値は変更できません。つまり、エントリに何かを割り当てた場合、エントリが指すオブジェクトを変更せずに、新しいオブジェクトを導入し、エントリへの参照を割り当てます。例:
_a = 1
d = locals()
d['a'] = 300
# d['a']==300
locals()
# d['a']==1
_
最適化に加えて、これは次のことを行います。
LOCALS['a']
_に保存しますLOCALS
は内部ローカルスコープでなければなりません)SINGLETON
オブジェクトを作成しますSINGLETON
を更新して、LOCALS
のすべてのエントリを参照するようにしますSINGLETON
のポインターを_LOCALS['d']
_に格納しますd['a']
_に格納しますSINGLETON
も更新されます。LOCALS
はnot更新されるため、ローカル変数a
または_LOCALS['a']
_は引き続きNumber(1 )locals()
が再度呼び出され、SINGLETON
が更新されます。d
はSINGLETON
ではなくLOCALS
を参照しているため、d
も変更されます!この驚くべき詳細の詳細、なぜ_
1
_がシングルトンであるのに_300
_はそうでないのか、 https://stackoverflow.com/a/30635 を参照してくださいただし、忘れないでください。数字は不変なので、数字を別の値に変更しようとすると、別のオブジェクトを効率的に作成できます。
結論:
Python 2をPython 3(コードを変更する場合を除く)の方法はありません)のexec
動作に戻すことはできません。プログラムフロー外のローカル変数を変更します。
ただし、Python 3の動作をPython 2にすることができます。これにより、今日、あなたは、 Python 3またはPython 2.これは、(新しい)Python 2でexec
関数のような引数も(実際、これらは2または3タプルです)、Python 3から知られる同じセマンティクスで同じ構文を使用できます。
_exec "code"
_
(Python 2)でのみ動作します)は(Python 2および3で動作します):
_exec("code", globals(), locals())
_
ただし、_"code"
_はこの方法でローカルの囲みスコープを変更できないことに注意してください。 https://docs.python.org/2/reference/simple_stmts.html#exec も参照してください
最後の言葉:
Python 3でのexec
の変更は適切です。最適化のため。
Python 2では、不変のコンテンツを含むすべてのローカル変数の状態が予期せず変更される可能性があるため、exec
全体で最適化できませんでした。関数呼び出しの_は、他のすべての関数と同様にexec()
にも適用されます。
正確に説明できないのではないかと思いますが、基本的には関数内のbがローカルであり、exec()
がグローバルbに割り当てられているように見えるという事実から来ています。関数内でグローバルであるようにbを宣言する必要がありますand execステートメント内で。
これを試して:
_from sys import version
print(version)
def execute1(a, st):
b = 42
exec("b = {}\nprint('b:', b)".format(st))
print(b)
def execute2(a, st):
global b
b = 42
exec("global b; b = {}\nprint('b:', b)".format(st))
print(b)
a = 1.
execute1(a, "1.E6*a")
print()
execute2(a, "1.E6*a")
print()
b = 42
exec("b = {}\nprint('b:', b)".format('1.E6*a'))
print(b)
_
それは私に与えます
_3.3.0 (default, Oct 5 2012, 11:34:49)
[GCC 4.4.5]
b: 1000000.0
42
b: 1000000.0
1000000.0
b: 1000000.0
1000000.0
_
関数の外側で、グローバルbが自動的に選択されることがわかります。関数内では、ローカルbを印刷しています。
exec()
は常にグローバルbを最初に使用するので、execute2()
ではexec()
関数内で宣言する必要がないと思っていたことに注意してください。 。しかし、私はそれがうまくいかないことがわかります(これは私が正確に説明できない部分です)。