首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >绑定事件后Tkinter如何处理lambda?

绑定事件后Tkinter如何处理lambda?
EN

Stack Overflow用户
提问于 2019-03-10 23:35:22
回答 1查看 1.4K关注 0票数 0

我正在尝试编写一些代码,将Entry框的值发送到基于绑定的函数。从技术上讲,我可以在下面的代码中得到我想要的行为,但我不知道为什么它会工作;( b)我很确定我没有以最仿生的方式来做这件事。我很肯定我误解了eventlambda,或者两者兼而有之。

Entry框下面的代码中,当绑定触发时称为input_box1inp_var1.get()代码只获取默认值,而不是输入到该框中的任何内容。换句话说,test1函数将打印..。

Test1 Foo

..。不管你在条目中输入了什么。

input_box2上的绑定与我所期望的完全一样。我在那里输入任何内容,然后单击其他地方,然后打印新条目。但是,我不明白为什么我的lambda不想要event,或者为什么我需要重复inp_var2.get()调用。

如果有人知道引擎盖下面是怎么回事,我很想听听!下面是代码:

代码语言:javascript
运行
复制
from tkinter import *
from tkinter import ttk

def test1(event, i):
    print('Test1', i)

def test2(event, i):
    print('Test2', i)

root = Tk()
title_label = Label(root, text='This does not work!')
title_label.grid(column=0, row=0)

inp_var1 = StringVar(value='Foo')
input_box1 = Entry(root, textvariable=inp_var1)
input_box1.grid(column=0, row=1)

inp_var2 = StringVar(value='Bar')
input_box2 = Entry(root, textvariable=inp_var2)
input_box2.grid(column=0, row=2)

input_box1.bind('<FocusOut>', lambda event, i=inp_var1.get(): test1(event, i))
input_box2.bind('<FocusOut>', lambda i=inp_var2.get(): test2(i, inp_var2.get()))

root.mainloop()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-11 00:16:12

这和Tkinter本身没什么关系。与其说它与lambda连接,不如说它与一般的Python连接。

将这两种方法都去掉,并考虑下面的Python程序:

代码语言:javascript
运行
复制
def f(x=3, y=4):
    print('x =', x, 'y =', y)

f(0, 0)
f(0)
f()

假设Python3(或from __future__ import print_function)在运行时,它会打印:

代码语言:javascript
运行
复制
x = 0 y = 0
x = 0 y = 4
x = 3 y = 4

这是因为对f的第一次调用传递给0, 0,因此xy都绑定为零。对f的第二个调用只传递0,因此x绑定到0y绑定到它的默认值4。第三个调用根本不传递任何内容,xy都绑定到它们的默认值。

(到目前为止,这一切都应该足够清楚。)

现在让我们小题大做一下。我将继续假设Python3,这样input就意味着在Python2中我们必须使用raw_input来实现:

代码语言:javascript
运行
复制
def f(x=input('enter default x: '), y=input('enter default y: ')):
    print('x =', x, 'y =', y)

print('about to call f three times')
f(0, 0)
f(0)
f()

在运行这个示例程序之前,请考虑一下您期望它做什么。然后运行它-这是我的结果:

代码语言:javascript
运行
复制
$ python3 t.py
enter default x: hello
enter default y: world
about to call f three times
x = 0 y = 0
x = 0 y = world
x = hello y = world

为什么在我们第一次调用它之前就读取了xy的默认值?为什么它没有在每次调用中读取xy的新默认值?

想一想,然后继续读下去。

真的,去做吧。问一问为什么输入发生在这些奇怪的时刻。

既然你已经想过了..。

但它确实做到了。这是关键所在。参数的默认值是在执行def语句时捕获的。def语句将名称f绑定到我们的函数,在查看函数的主体后,它实际上是在Python文件时运行的。函数本身将在print调用之后运行,然后再运行到第一个f调用。

Python中的lambda只是一种匿名函数定义。而不是:

代码语言:javascript
运行
复制
def square(x):
    return x * x

我们可以写:

代码语言:javascript
运行
复制
square = lambda x: x * x

lambda表达式定义了一个新的函数类项,即lambda函数,您不能在其中一个表达式中使用if/else类型语句,而它们会自动返回表达式的值。在本例中,我们的lambda函数有一个名为x的参数。函数返回x * x

外部赋值square =将这个lambda函数绑定到名称square,就好像我们已经做了def square(x)一样。所以这基本上只是一个句法技巧:我们可以有一个真正的函数,比如square,带有参数,或者一个有限的lambda函数,它只能使用表达式,比如我们几乎立即绑定到名称square的匿名函数。

但是,参数部分的工作原理是相同的。就像finput一样,如果我们绑定x

代码语言:javascript
运行
复制
square = lambda x=3: x * x

或者:

代码语言:javascript
运行
复制
square = lambda x=int(input('choose a default for x now> ')): x * x

lambda表达式本身执行时,这种情况只发生一次。该函数现在有一个带有默认值的变量x

稍后,当我们调用该函数时,我们可以为x提供一个值,或者让它默认。如果我们不提供一个值,Python使用它在执行包含lambda的行时早些时候捕获的缺省值,而不是现在调用lambda函数时。

这对Tkinter来说也是一样的。你写道:

代码语言:javascript
运行
复制
input_box2.bind('<FocusOut>', lambda i=inp_var2.get(): test2(i, inp_var2.get()))

但这和写作差不多:

代码语言:javascript
运行
复制
def f(i=inp_var2.get()):
    test2(i, inp_var2.get())

input_box2.bind('<FocusOut>', f)

不过,您不必在这里提出函数名f。函数的lambda变体没有名称,但它仍然只是一个函数。(因此,当我们执行square = lambda ...时,lambda函数没有名称。名称square是变量的名称,而不是函数的名称。)该变量仅绑定到函数,以便square(10)调用它。)

无论如何,后来,当Tkinter有一个与<FocusOut>匹配的事件时,Tkinter调用f .或者,如果使用lambda,则调用未命名的lambda函数。Tkinter为该函数提供了一个参数;它提供的一个参数是事件。因此,上述i的默认值与f无关--您可以这样做:

代码语言:javascript
运行
复制
def f(i=None):
    test2(i, inp_var2.get())

或者:

代码语言:javascript
运行
复制
def f(i='hello world'):
    test2(i, inp_var2.get())

因为当Tkinter调用f时,它总是为i提供一个实际的参数。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55093502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档