【问题标题】:callback functions associated with tkinter traces in Python3Python3 中与 tkinter 跟踪相关的回调函数
【发布时间】:2013-03-27 12:55:03
【问题描述】:

我提出这个问题是因为我刚刚看到了这个问题What are the limitations of callback functions associated with Tkinter traces?

我使用lambda 添加另一个参数。 代码如下:

from tkinter import *

def callbackfunc(*args, **kwargs):
    print(args,kwargs)

class App(object):
    def __init__(self, master):
        frame = Frame(master)
        frame.pack()

        optionvalue = IntVar(master)
        optionvalue.set(2)
        optionvalue.trace("w",lambda a,b,c,x='test':callbackfunc(x))
        self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4)
        self.optionmenu.pack()

root = Tk()
app = App(root)
root.mainloop()

我的输出:('test',) {} 我想知道的是: 如果我使用 lambda,为什么不输出其他 3 个参数?

【问题讨论】:

    标签: python python-3.x callback tkinter


    【解决方案1】:

    让我们看看这一行:

    optionvalue.trace("w",lambda a,b,c,x='test':callbackfunc(x))
    

    这在概念上与这样做几乎相同:

    def i_dont_care_what_the_name_is(a,b,c,x='test'):
        callbackfunc(x)
    optionvalue.trace("w", i_dont_care_what_the_name_is)
    

    当跟踪触发时,它使用三个值调用 lambda——这是记录在案的行为。不管你是否使用 lambda,Tkinter 都会总是将三个参数传递给回调。

    您已创建 lambda 以获取第四个可选值,这是使用 lambda 的一种非常常见的方式。但是,在您的 lambda 中,您显式调用 callbackfunc 并且只传递一个值 x。

    它是这样工作的:回调用三个参数调用你的 lambda。您已将 lambda 定义为具有额外的第四个参数。然后 lambda 调用您的回调,但您只给它一个参数。

    那么,“如果我使用 lambda,为什么不输出其他 3 个参数?”这个问题的答案。是“因为您只是将其中一个参数从 lambda 内部传递给您的其他函数”。

    【讨论】:

    • 如果我使用lambda x='test':callbackfunc(x),那么它会引发TypeError:<lambda>() takes from 0 to 1 positional arguments but 3 were given。我想确定原因是否是:当不使用lambda时,Python会自动将3个参数传递给函数/方法它应该接收这些参数。然后使用 lambda,这次是 lambda 接受这些参数,lambda 请求显式传递参数。是这个原因吗?
    • 你和 Schnouki 都没有对此作出解释。
    • @laike9m:当 Tkinter 调用回调时,它总是会传递三个参数,因为这是设计的。如果您将 lambda 定义为仅采用一个参数,这就是为什么会出现该错误的原因。回调必须至少采用三个参数。这与您是否使用 lambda 无关——tkintre 不知道。它将总是传递三个参数。您必须提供一个至少接受三个参数的回调。它可以是一个适当的函数,也可以是一个 lambda,但无论如何,它必须至少带有三个参数。
    【解决方案2】:

    问题出在这一行:

    optionvalue.trace("w",callbackfunc())
    

    不是将callbackfunc 传递给optionvalue.trace,而是调用它——没有参数,因此是你的输出。

    你应该改用这个:

    optionvalue.trace("w", callbackfunc)
    

    没有括号,如question you linked

    【讨论】:

    • 我已经编辑了我的问题,事实上这就是我想问的。谢谢
    • 好吧,你仍然用x 调用callbackfunc,忽略abc。你应该改用lambda a, b, c, x="test": callbackfunc(a, b, c, x) 之类的东西。
    • lambda a, b, c, x="test": callbackfunc(a, b, c, x) 肯定有效,但如果我使用lambda x='test':callbackfunc(x),那么它会提高TypeError: <lambda>() takes from 0 to 1 positional arguments but 3 were given
    • 自相矛盾的是,TypeError 告诉我虽然我写了callbackfunc(x),但我实际上将a、b、c 传入了,但我无法从*args 得到它们跨度>
    • 不,这意味着您的 lambda 被调用(由 Tkinter)使用 3 个参数,但您只使用 1 个(可选)arg 定义它。也许你应该只使用optionvalue.trace("w", print) 来检查它是如何被调用的(print 是 Python 3 中的一个函数)。
    猜你喜欢
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多