11

私は C++ のバックグラウンドがあり、Python を学ぼうとしています。

私は C++ の仮想関数を理解していますが、残念ながら Python でのクロージャの遅延バインディングの意味を理解していません。

リンク: https://gist.github.com/deemson/8efabf56d67623ead804 (動作しなくなりました)

チュートリアルからコピー&ペースト:

functions = []
for n in [1, 2, 3]:
    def func(x):
        return n*x
    functions.append(func)

# You would expect this to print [2, 4, 6]
print(
    'calling a list of bad closures and output is: {}'
    .format(str([function(2) for function in functions]))
)

ここで正確に何が起こっているのですか?関数がリストに追加されると、どのような値になりますか? 誰かが私が理解できるようにこのコードを単純化してもらえますか?

4

2 に答える 2

9

Notice this, you can create functions on runtime, more or less like lambdas in c++. So basically you are iterating over a list, making n take values 1,2 and 3

for n in [1, 2, 3]:
    def func(x):
        return n*x

so, by each iteration you are building a function named func, with takes a value and multiplies it for n. By appending it to the functions list you will have this functions stored, so you can iterate over the list to call the functions.

[function(2) for function in functions]

By doing this you call each of the functions stored with the value 2, you would expect this to output [2, 4, 6] ([1*2, 2*2, 3*2]), but instead it returns [6, 6, 6], WHY?, thats becouse every function use n for its computation, so they are not really doing 1*x, 2*x and 3*x but actually n*x and since n is bonded in last time to 3 all functions are doing 3*2 wich becomes 6.

Play around with the python console to check it properly.

于 2016-04-06T22:45:28.173 に答える
3

C++ 言語では、関数へのポインタがリストに追加されます。forループの後、 3 つの異なる関数 ( 、および)functionsへのポインターが含まれます。n への依存性に注意してください。n が変化すると、これらの関数の動作も変化し、それらはすべて同等です。func(x) = n * xfunc(x) = n * xfunc(x) = n * x

コードの 2 番目の部分では、ポインタがリストから抽出され、3 つの関数のそれぞれが の引数で評価されます2

明確にするために、さらに例を示します。これを行うと想像してください:

>>> functions
[<function func at 0x0239AA70>, <function func at 0x0239AAB0>, <function func at 0x0239AB30>]
>>> g = functions[2]
>>> g
<function func at 0x0239AB30>
>>> g(10)
20
>>> g(100)
200

最初の行で見られるのは、関数に 3 つの異なる関数へのポインターが含まれていることです。次の行は、リストから 3 番目のポインター ( を参照func(x) = n * x) を抽出し、それを g に割り当てます。g(x) = n * x事実上、この呼び出しで関数を定義しました。g引数で評価できるようになりました。

すべての関数は に依存しているためn、 を変更nすると動作が変わることに注意してください。

>>> n = 100
>>> g(10)
1000
于 2016-04-06T22:50:17.847 に答える