0
0

More than 1 year has passed since last update.

Python メモ:for文で動的にlambda式を使う

Posted at

はじめに

メンテナンスツール(スクリプト)を数々作成したため、いちいちスクリプトファイルを選んで実行するのは面倒でした。そこで、TkinterによるSelect Launcherを作り、選択実行できるようにしました。
ボタンを作るたびに、その数分tk.Button宣言を記述していては、長々としたコードになってしまうので、lambda式を使用してコード量を減らします。
この時のlambda式の記述の仕方をメモに残しておきます。

lambda式

Python 公式ドキュメント

6.14. ラムダ (lambda)

lambda_expr ::=  "lambda" [parameter_list] ":" expression

ラムダ式 (ラムダ形式とも呼ばれます) は無名関数を作成するのに使います。 式 lambda parameters: expression は関数オブジェクトになります。 この無名オブジェクトは以下に定義されている関数オブジェクト同様に動作します:

def <lambda>(parameters):
    return expression

引数の一覧の構文は 関数定義 を参照してください。ラムダ式で作成された関数は文やアノテーションを含むことができない点に注意してください。

記述

最終的なソースコードは、後述します。

与えられた文字列リストselect_listをもとにボタンが縦に並びます。
for文での記述箇所は、以下の通りです。

    for name in self.select_list:
        btn = tk.Button(
            root,
            text=name,
            command=lambda key=name: self.btn_clicked(key)
        )
        btn.pack(
            side=tk.TOP, fill=tk.BOTH,
            padx=sp, pady=sp, ipadx=sp, ipady=sp
        )

ポイントは、lambda式の**key=name:**です。

これを以下のようにして、直接変数nameを与えるとどうなるでしょうか?

            command=lambda self.btn_clicked(name)

このように記述すると、self.btn_clicked関数に渡される値は、全てFor分の最終結果である「name='C'」となってしまいます。

Select Dialog(Launcher)

文字列のリストを渡すと、以下のようなダイアログが表示されるプログラムです。

image.png

ソースコード(最終)

import tkinter as tk


class select_dialog():
    def __init__(self, select_list: list) -> None:
        self.select_list = select_list
        self.create_dialog(self._tk_root_())

        return

    def _tk_root_(self) -> tk.Tk:
        item = len(self.select_list)
        screen_w, screen_h = 240, item*45
        root = tk.Tk()
        root.attributes('-topmost', True)
        root.title(f'Select Menu')
        geo_string = f'{screen_w}x{screen_h}'
        root.geometry(geo_string)
        root.lift()
        root.focus_force()

        return root

    def create_dialog(self, root):
        sp = 5

        for name in self.select_list:
            btn = tk.Button(
                root,
                text=name,
                command=lambda key=name: self.btn_clicked(key)
            )
            btn.pack(
                side=tk.TOP, fill=tk.BOTH,
                padx=sp, pady=sp, ipadx=sp, ipady=sp
            )

        root.mainloop()
        return

    def btn_clicked(self, name):
        print(name)


if __name__ == '__main__':
    select_list = ['A', 'B', 'C']
    select_dialog(select_list)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0