2017-03-25 9 views
2

私は困惑しています。次の2つのコードが同じように動作しないのはなぜですか?最初のサンプルでキーワード引数とdictアンパック結果が異なる

1)

for attr in ("size", "pos"): 
    self.bind(**{attr: lambda *args: setattr(self.background, attr, self.__getattribute__(attr))}) 

2)

self.bind(size=lambda *args: setattr(self.background, "size", self.__getattribute__("size"))) 
self.bind(pos=lambda *args: setattr(self.background, "pos", self.__getattribute__("pos"))) 

、キーワード引数を直接与えられます。 もう一つは、dictを解凍することによってキーワード引数が与えられます。

奇妙なKivyの奇妙なものか何かgetattribute

答えて

4

これは、Pythonでクロージャがどのように機能するかを示します。内部関数(この場合はラムダ)は、その値ではなく変数attrへの参照を取得します。ファンクションの作成後にattrを変更すると、ファンクションで使用されるattrの値も変更されます。したがって、両方のラムダは、同じ値のattr(ループに最後に表示されたもの、"pos")を参照することになります。

これを修正するには、ラムダのデフォルト引数値を使用して値を取得できます。これらは、関数が構築されたときに完全に評価されます。

for attr in ("size", "pos"): 
    self.bind(**{attr: lambda *args, attr=attr: setattr(self.background, attr, self.__getattribute__(attr))}) 
+0

これは意味があります。優秀な説明をありがとう! –

関連する問題