for prop in public_props:
setattr(proxy, 'get_%s'%prop, lambda: self.get_prop(prop))
ここでプロキシは私が提供したプロキシ オブジェクト。self のいくつかのパブリック属性を公開します。非パブリック属性へのアクセスを制限したいため、このプロキシには self への参照を格納したくありません。それ以外の場合は、アクセス許可の制限がない Python で、プロキシのようなものを使用できます。_orig_self.some_private_prop 経由でアクセスするのは簡単です。そこで私は最終的に上記のアプローチを選択しました。
残念ながら、今述べたように、for は毎回個別のスコープを作成しないため、クロージャーはすべて同じ変数を参照し、その結果、すべての属性値が最後の属性として取り出されます。このような奇妙なバグを見て、それが C/C++ にある場合は、メモリまたはポインタの問題であると疑う必要があります。しかし、長い間考えた後、ついに気づきました!しかし、Python には Ruby ほど便利なものはなく、lambda も使い物にならないので、最終的にはローカル関数を定義することで解決しました:
Copy code コードは次のとおりです: def proxy_prop(name):
setattr(proxy, 'get_%s'%prop, lambda: self.get_prop(name)
for prop in public_props:
proxy_prop(prop)
最後に、先ほどの Ruby の例に関してもう 1 つ言いたいのですが、それぞれと for の実行順序を逆にすると、異なる結果が得られます。 :
コードをコピー コードは次のとおりです:arr = ['a', 'b', 'c']
h1 = Hash .new
h2 = Hash.new
for e in arr
h2[e] = lambda { e+'!' }
end
arr。 each { | e|
h1[e] = lambda { e+'!'}
}
h1['a'].call # => ['a '].call # => 'c!'
これで両方とも 'c!' になります!これは、Ruby 1.8 の実装では、ブロックのパラメータが通常のラムダ関数のパラメータのように単純ではなく、ローカル変数やグローバル変数などに代入できるためです。前の for ステートメントは現在のスコープにローカル変数として e を作成したため、この方法では参照されるたびに値が同じになり、隠れたバグが発生します。
ありがたいことに、ブロックのこの「機能」は Ruby 1.9 で削除され、ブロックのパラメーターは通常のパラメーターのみにできるため、この問題はもう存在しません。 1.9 ができるだけ早く普及することを願っています。