3

重複の可能性:
この Python 関数のラムダ式で何が起こっているのでしょうか?
(ラムダ)関数クロージャはPythonで何をキャプチャしますか?

たとえば、文字列 ['a', 'b', 'c'] のリストがあります。

そのリスト内の要素 ('a'、'b'、および 'c') をキーとして 1 つの辞書を生成し、キーを値として出力する関数 (print('a')、print('b) ')、印刷 ('c'))

  from __future__ import print_function
  l = ['a', 'b', 'c']
  m = {k: lambda : print(k) for k in l}

上記のコードを書きました。しかし、結果は正しくありません

  m['a']()
  c
  m['b']()
  c

そこでラムダを使用しない場合、私はそれを知っています

m = {k:print(k) for k in l}

これは問題ありません。しかし、ラムダがここで機能しない理由を知りたいです。

これを解決する方法はありますか?ありがとう

4

2 に答える 2

3

c各キーの出力として取得する理由はc、 が反復の最後に来るためです。したがって、 の最終値xcここにあり、プログラムは次のように展開できます。

    for x in lis:
        def func():
            print(x)
        dic[x]=func

ここで、関数は実際にはxローカル変数ではなくグローバル変数の値にアクセスしています。そして、反復の最後にあるxように、答えとしてc得られます。c

したがって、値をローカル変数に格納するには、デフォルトの引数を使用する必要があります。

正しいコード:

    In [2]: lis=['a', 'b', 'c']

    In [3]: dic={x:lambda i=x:print(i) for x in lis}

    In [4]: dic['a']
    Out[4]: <function __main__.<lambda>>

    In [5]: dic['a']()
    a
    In [6]: dic['b']()
    b

また:

In [16]: for x in lis:
    def func(i=x):
        print(i)    
    dic[x]=func
   ....:     

In [17]: dic['b']()
b
于 2012-12-10T21:07:29.487 に答える
2

遭遇する基本的な問題は、labda 式のバインディングに関係しており、その方向でいくつかの質問を見つけることができます (たとえば、Python での「ラムダ バインディング」とは?またはPython ラムダのローカル値へのバインディング) 。

一般的な解決策はfunctools.partial、問題を回避するために使用することです。

from __future__ import print_function
import functools

l = ['a', 'b', 'c']
m = {k: functools.partial(print, k) for k in l}
于 2012-12-10T21:15:49.233 に答える