3

この(かなり無意味な)javascriptコードを考えてみましょう:

function make_closure() {
    var x = 123, y = 456;
    return function(varname) { return eval(varname) }
}

closure = make_closure()
closure("x") // 123
closure("y") // 456

から返される関数にはmake_closureスコープ変数への参照は含まれていませんが、呼び出されたときにそれらの値を返すことができます。

Pythonで同じことをする方法はありますか?

def make_closure():
    x = 123
    return lambda varname: ...no "x" here...

closure = make_closure()
print closure("x") # 123

言い換えれば、スコープを定義する際に変数について明示的に言及せずに変数について「知っている」クロージャーを作成するにはどうすればよいでしょうか。

4

4 に答える 4

5

これはおそらく、正確に同等のものに最も近いものです。

def make_closure():
  x = 123
  l = locals()
  return lambda(varname): eval(varname, None, l)

closure = make_closure()
print closure("x") # 123

最終的に、問題は x がローカル クロージャによってキャプチャされなかったことではなく、ローカル スコープが eval に渡されなかったことです。

eval 関数の詳細については、http://docs.python.org/library/functions.html#evalを参照してください。

言うまでもなく、これは非常に Pythonic な作業ではありません。Python で実際に eval を呼び出したいと思うことはほとんどありません。そう思う場合は、一歩下がってより大きなデザインを再考してください。ただし、それを使用する必要がある場合は、Javascript eval との違いを理解する必要があります。最終的にはより強力です。動的スコープをシミュレートしたり、exec の簡易バージョンとして使用したり、任意に構築された環境でコードを評価したりするために使用できますが、それはよりトリッキーであることも意味します。

于 2012-06-19T22:29:13.537 に答える
2

人々はすでに使用について言及していlocals()ます。別の、確かに柔軟性に欠けるアプローチはnonlocal、Python 3 で new キーワードを使用することです。

>>> def make_closure():
...     x = 123
...     def return_var(varname):
...         nonlocal x
...         return eval(varname)
...     return return_var
... 
>>> closure = make_closure()
>>> closure("x")
123

これには、閉じて参照したい外部スコープの変数に明示的にラベルを付ける必要があるという明らかな欠点があります。

于 2012-06-19T22:35:25.710 に答える
1

Javascript の場合とほぼ同じように、Python で変数を閉じることができます。

def foo():
  x = 123
  return lambda y: x+y

q = foo()

print q(5)

http://ideone.com/Q8iBg

ただし、いくつかの違いがあります。たとえば、親のスコープ内の変数には書き込めません (書き込もうとすると、代わりにローカル スコープの変数が作成されます)。また、Pythoneval()には親スコープが含まれていません。

eval()親スコープからローカルを明示的に取得し、ローカル引数として子スコープに渡すことで、これをバイパスできますeval()が、ここでの本当の問題は、なぜこれを行う必要があるのか​​ということです。

于 2012-06-19T22:27:08.890 に答える
0

Python 2.x では、これには大規模なクラッジングが必要です。ただし、Python 3.x では、'nonlocal' キーワードが導入され、すぐ外側のスコープ内の変数にアクセスできるようになりました。

詳細については、ここで確認する価値があるかもしれません: Python 2.x の非ローカル キーワード

于 2012-06-19T22:34:00.660 に答える