参考:https://stackoverflow.com/questions/6920302/how-to-pass-arguments-to-a-button-command-in-tkinter
背景说明
tkinter 组件中经常会绑定一些事件,实现的方向是添加command
关键字,后面跟一个实现的函数方法,如:command = func()
。但有时你还需要向 func
函数传递必要的参数,我们常见的想法是这样:
button = tk.Button(root, text="Show me", command=action(args))
遗憾的是这样却不能实现你想要的结果。那如何才能实现传递参数呢?下面介绍两种简单的方法。
方法一、使用 partial
函数
代码示例:
from functools import partial
button = tk.Button(root, text="Show me", command=partial(func, arg1, arg2,...))
我们可以通过使用 functools
模块中的 partial
对象来传递参数。
用例子来说明,下面是给菜单添加item并绑定事件:
colors = ['黄色','亮紫','紫灰','亮蓝','深绿','鲜红','洋红','灰色']
for c in colors:
zrlbMenu.add_command(label=c, command=partial(mark_zrlb,c))
就会根据变量c
,生成多项item执行事件。这里主要起作用的是 partial
函数,它是一个偏函数
。
partial
函数的语法如下:
functools.partial(func, *args, **keywords)
偏函数:是在已有的函数基础上生成一个新的函数
,这新函数的功能和已有函数相同,但是,这个新函数的部分参数已被偏函数确定。简单来说,偏函数
适合当函数中的某些参数值在某些场景下是定值的时候,将其简化。什么意思呢?就是省略某些不变的参数,使得代码会更加简洁
。
例如,要在 menu
目录下新建若干文件夹,原代码:
import os
from os import mkdir
mkdir(os.path.join('./menu', 'dir1' ))
mkdir(os.path.join('./menu', 'dir2' ))
mkdir(os.path.join('./menu', 'dir3' ))
使用 partial
修改之后,代码如下:
import os
from os import mkdir
from functools import partial
menu_join = partial(os.path.join, './menu')
mkdir(menu_join('dir1'))
mkdir(menu_join('dir2'))
mkdir(menu_join('dir3'))
menu_join
是通过偏函数 partial()
创建的一个新的函数,而不是赋值变量。menu_join
这个函数在执行时,先调用 os.path.join
并将 './dest'
作为参数传给 os.path.join
,然后再传入 "dir"
。
- 它是用于创建一个类似原函数但有固定参数的偏函数,从
偏
字可以看出,它是一个辅助函数。 - 它一共有三个部分:
1). 第一个部,即第一个参数一个函数
,这个函数可以是你定义的,也可以是 python 内置函数
2). 第二部分,是一个可变参数
,*args
3). 第三部分,是一个关键字参数
- 它的作用是:将所作用的函数作为
partial()
函数的第一个参数,原函数的各个参数依次作为partial()
函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。
总结来说:当函数的参数个数太多,需要简化时,使用 functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
方法二、使用 lambda
函数
代码示例:
button = tk.Button(root, text="Show me", command=lambda:func(param))
我们可能通过 python 中的 lambda
函数来创建一个临时的、一次性的简单函数用来实现传递参数。但是注意,这里有一个小小的细节,lambda
函数只会在调用时执行内部语句。也就是说,如果你传递的参数是一个变量
,并且这个变量值是随着条件变化的,使用它来实现时,调用时就会传入这个变量最后的值,可能就不是你预期想要传入的值。
还是上面那个菜单的例子:
colors = ['黄色','亮紫','紫灰','亮蓝','深绿','鲜红','洋红','灰色']
for c in colors:
zrlbMenu.add_command(label=c, command=lambda:mark_zrlb(c))
变量c
是变化的,但实际的效果表现出来是,c
取的值永远是最后一个值'灰色'
。
所以,lambda
这一方法是应用于参数是固定的变量。例如:
btnLable= tk.Button(root, text="0")
def change_number(num):
counter = int(str(btnLable['text']))
counter += num
btnLable.config(text=str(counter))
button = tk.Button(root, text="Increase", command=lambda: change_number(5))
lambda
函数的语法如下:
lambda: argument_list: expression
常见的 lambda
函数示例:
lambda x, y: x*y # 函数输入是x和y,输出是它们的积x*y
lambda:None # 函数没有输入参数,输出是None
lambda *args: sum(args) # 输入是任意个数参数,输出是它们的和(隐性要求输入参数必须能进行算术运算)
lambda **kwargs: 1 # 输入是任意键值对参数,输出是1