lambdaの内包表記で躓いた話
-
結論:
lambda式の参照は呼び出されたタイミングで決まる本題:
またミュータブル、イミュータブル関連で躓いたのでメモ
リスト内辞書にラムダ式を持たせて比較を行おうとした。l = ["a", "b", "c", "d", "e"] funcL = [ { "str": s, "func": lambda x: x == s } for s in l ] checkStr = "a" for func in funcL: print(checkStr, func["str"], func["func"](checkStr)) # >> std out # >> a a False # >> a b False # >> a c False # >> a d False # >> a e False
なんでaとaがFalseになってるの!?となったところで確認してみるとfunc["func"]で比較しているsがすべてeになっている。
l = ["a", "b", "c", "d", "e"] funcL = [ { "str": s, "func": lambda _x: print(s) } for s in l ] for func in funcL: func["func"](None) # >> std out # >> e # >> e # >> e # >> e # >> e
いろいろ試したところラムダ式の中身が確定されるのはラムダ式が呼び出されたタイミングで参照されている値であり、今回の例ではそれぞれのラムダ式が呼び出された時点でのsの参照先が"e"のためすべてのラムダ式で"e"と比較されていたらしい。
解決策:
おとなしくラムダ式を使わずに比較する。l = ["a", "b", "c", "d", "e"] checkStr = "a" for s in l: print(checkStr, s, checkStr == s) # >> std out # >> a a True # >> a b False # >> a c False # >> a d False # >> a e False