質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

571閲覧

Pythonのfor文内でlambda関数を用いて定義した関数が意図通りの挙動をしないです。

shota_cnmn

総合スコア2

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2023/05/23 17:02

編集2023/05/23 17:34

ご教示願います

「ソースコード」を実行すると、「期待した出力」のように出力されず、「実際の出力」のように出力されてしまう理由・仕組みを知りたいです。
ご教示よろしくお願いいたします。

ソースコード

Python

1func_list = [] 2 3for i in range(3): 4 func_list.append(lambda: print(i)) 5 6for func in func_list: 7 func()

期待した出力

0 1 2

実際の出力

2 2 2

【参考】lambda関数を用いない場合

以下の場合は期待通りに出力されます。

Python

1func_list = [] 2 3for i in range(3): 4 func_list.append(print(i)) 5for func in func_list: 6 func

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Python公式ドキュメントのよくある質問に書いてあります。
https://docs.python.org/ja/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result

引数のデフォルト値が定義時に評価されることを利用して

python

1func_list = [] 2 3for i in range(3): 4 func_list.append(lambda i=i: print(i)) 5 6 7for func in func_list: 8 func()

が常套手段です。

読みにくいと感じたなら、よくある質問に書いてあるコードのように

pyhton

1 func_list.append(lambda x=i: print(x))

と変数名を別にして書くのがいいです。

投稿2023/05/23 23:19

編集2023/05/23 23:28
quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/05/24 03:25 編集

なるほど。引数のデフォルト値という方法があるんですね。これは簡便だ。 他の多くの言語だとデフォルト値は呼び出し時に評価されるので、Python限定の技ですね。
guest

0

ベストアンサー

行6の直前では、iの値は2なので、print(i)すれば2が表示されます。

「その時点のiの値」を保存しておきたければ別の変数が必要です。
こういうの(=クロージャー)は、Pythonではやったことないですが、こうですかね。

Python

1for i in range(3): 2 func_list.append((lambda x : (lambda : print(x)))(i))

投稿2023/05/23 17:40

編集2023/05/23 17:41
otn

総合スコア84553

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shota_cnmn

2023/05/23 18:00

ご回答ありがとうございます。 なるほど、4行目で`print(i)`のような関数を実行する場合はそのときの`i`の値で実行されるけど、あくまで定義の場合はそのときの`i`の値は関数に保存されず、グローバル変数として保持されるため、6行目で呼ばれたときにそのときの`i`の値`2`で関数が実行されるということですね。(もしよかったら、私の理解が間違ってたら遠慮なく訂正していただきたいです。) 大変勉強になりました。ありがとうございました。 クロージャーについて初めて知ったので、こちらに関しても勉強しようと思います。
shota_cnmn

2023/05/23 18:18

修正ありがとうございます。 グローバル、ローカル関係なく関数実行時は変数のidで値を参照するという感じですね。
otn

2023/05/24 02:55

はい。グローバルかどうかは本質じゃないので文言を削除しました。 lambdaの内側の変数なのか、lambdaの外側の変数を参照しているのか、の違いです。
otn

2023/05/24 03:30

他の方の回答にあるように「Pythonでは引数のデフォルト値は関数定義時に評価される」という特徴を使うと、クロージャーを使わずともコンパクトに書けます。 (他の多くの言語では引数のデフォルト値は、関数定義時じゃなくて関数呼び出し時に評価されるので、この技は使えない)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問