2012-06-18 20 views
7

ループでは、後で2つのノードの2つのvalue()を比較することをやめようとしています。Pythonでラムダを使った遅延評価

class Node(): 
    def __init__(self, v): 
     self.v = v 
    def value(self): 
     return self.v 

nodes = [Node(0), Node(1), Node(2), Node(3), Node(4), Node(2)] 
results = [] 
for i in [0, 1, 2]: 
    j = i + 3 
    results.append(lambda: nodes[i].value() == nodes[j].value()) 

for result in results: 
    print result 

結果はすべてTrueです(すべてのlambdaについてi、j == 2,5です)。実際に呼び出されるまではラムダの実行を延期することはできますが、正しい変数バインディングを使用することはできますか?ラムダの表現は必ずしも平等というわけではありません。他にも多くの表現があります。

ありがとうございました!

+0

あなたがしようとしていることは本当にわかりません。ラムダ式はここで私には不要です。なぜresults.append(nodes [i] .value()== nodes [j] .value()) 'を実行できないのですか? – JAB

答えて

11

現在の値ijを外部スコープで表示するのではなく、関数にバインドするには、クロージャー値またはデフォルトの引数値を使用できます。これを行う最も簡単な方法は、あなたのラムダにデフォルト引数値を使用することです:

for i in [0, 1, 2]: 
    j = i + 3 
    results.append(lambda i=i, j=j: nodes[i].value() == nodes[j].value()) 

ここでは、クロージャとしてどのように見えるかです:

def make_comp_func(i, j): 
    return lambda: nodes[i].value() == nodes[j].value() 

for i in [0, 1, 2]: 
    j = i + 3 
    results.append(make_comp_func(i, j)) 
3

慣用的な方法は、デフォルトの引数を使用することです。

[f() for f in [lambda: i for i in range(3)]] 
[2, 2, 2] 

に変更し、これを:

[f() for f in [lambda i=i: i for i in range(3)]] 
[0, 1, 2] 
5

別のラムダで包み:

results.append((lambda x, y: lambda: nodes[x].value() == nodes[y].value()) (i, j)) 

またはよりよい方法で、partialで:

from functools import partial 

results.append(partial(lambda x, y: nodes[x].value() == nodes[y].value(), i, j)) 

デフォルト引数のトリックは...よく、トリックです、と私は避けることをお勧めしたいですそれ。

+1

+1の部分を示唆します。 – jdi

関連する問題