【python】複数のメソッドをラムダ式のリスト内包表記で指定したときの挙動が理解できない([f() for f in [lambda:s for s in ["m1", "m2"]]] != ["m1", "m2"]なのは何故か)
解決したいこと
発生している問題に示した挙動の理由が知りたいです。
発生している問題
>>> class Test:
... def __init__(self):pass
... [m1,m2] = [lambda self:s for s in ["m1", "m2"]]
...
>>> Test().m1()
'm2'
>>> Test().m2()
'm2'
Test().m1()
が'm1'
を返すことを期待していましたが、実際はそうはなりませんでした。
自分で試したこと
実験1.
>>> class Test(Test): # __init__の再定義が面倒なので過去に定義したTestを新しいTestに継承させた
... [print(s) for s in ["m1", "m2"]]
...
m1
m2
リスト内包表記においてlambda
式をprint
で置き換えたところ、ちゃんとm1
, m2
の順で標準出力されました。
→s
が2回とも'm2'
となっているわけではなさそうです
実験2.
>>> class Test(Test):
... [m1,m2] = [lambda self:s for s in ["m1", "m2"]]
... print(m1)
... print(m2)
...
<function Test.<listcomp>.<lambda> at 0x000001825FDA5280>
<function Test.<listcomp>.<lambda> at 0x000001825FDA5160>
>>> test = Test()
>>> test.m1 == test.m2
False
>>> test.m1() == test.m2()
True
print(m1)
とprint(m2)
で、id
が異なることから、m1
とm2
が同じオブジェクトになっているわけではなさそうです。
このことは、test.m1 == test.m2
がFalse
と評価されたことにより、インスタンス生成後も成り立つとわかりました。
考察
実験1より、s
は1回目には'm1'
、2回目には'm2'
と評価していることが分かります。
実験2より、m1
とm2
はid
の異なるオブジェクトであることが分かりました。
疑問
2つのcallable
なオブジェクトlambda self:s
とlambda self:s
について、返却値として指定されるs
が互いに異なり、
かつlambda self:s
自身も互いに別のオブジェクトとして登録されています。
ところが実際の返却値(lambda self:s)()
は互いに一致するのは何故でしょうか。
この疑問を一言でいうと、次の通りになります。
[f() for f in [lambda:s for s in ["m1", "m2"]]]
が['m2', 'm2']
となり、['m1', 'm2']
とならないのは何故ですか