【问题标题】:lambda working oddly with tkinterlambda 与 tkinter 奇怪地工作
【发布时间】:2013-03-08 23:35:09
【问题描述】:

我正在尝试使用 Tkinter 制作计算器。我一直在尝试清理代码,但遇到了障碍。创建按钮时,我使用以下代码:

Button(self,text="1",command=lambda: self.addkey("1"),width=self.defaultwidth,height=self.defaultheight).grid(row=5, column=0)
Button(self,text="2",command=lambda: self.addkey("2"),width=self.defaultwidth,height=self.defaultheight).grid(row=5, column=1)
Button(self,text="3",command=lambda: self.addkey("3"),width=self.defaultwidth,height=self.defaultheight).grid(row=5, column=2)

以下是调用的命令

def addkey(self,key):
            # Adds a given key to the display
            if len(self.displaytext) + len(key) <= self.maxlength:
                self.displaytext += key
                self.display["text"] = self.displaytext

当按顺序按下按钮 1、2 和 3 时,输出如下:

123

我一直在尝试清理代码,使其看起来更像:

for i in range(3):
    Button(self,text=str(i+1),command=lambda: self.addkey(str(i+1)),width=self.defaultwidth,height=self.defaultheight).grid(row=5, column=i)

这很好地添加了按钮,但是当依次按下 1、2 和 3 时,屏幕上会显示以下内容:

333

我想知道我是否错过了什么或者这根本不可能。

【问题讨论】:

  • 您能发布更多代码吗?我假设这个按钮创建代码是从类的__init__() 方法运行的?
  • 我认为这是一个经典的 Python 词法作用域陷阱

标签: python lambda tkinter


【解决方案1】:

啊,范围界定。当你这样做时:

command=lambda: self.addkey(str(i))

没有i“解析”为就在那里。您只是告诉 lambda 在调用时引用 i之后

for 循环结束后的任何时间,i = 3(最后一个值),所以当你的所有 lambda 表达式请求 i 时,他们都会得到 3

如果我没记错的话,你可以添加一个函数作为间接方法,它会从周围的范围内适当地“捕获”i

def add_key_f(i):
    return lambda self: self.addkey(i)

【讨论】:

  • 这个问题的经典解决方法(除了你提到的那个)是添加一个关键字 arg:command=lambda i=i: self.addkey(str(i))
  • 另一种选择:command=functools.partial(self.addkey, str(i)).
  • @BryanOakley 这有点脏,因为将值导入 lambda 是对关键字参数机制的滥用(否则不会使用或不需要 i 参数)。但是,它非常简短,易于理解,并且它一个 Python 习语,所以它的使用不应被视为混淆。
  • 默认如何设计来关闭词法范围内的变量?
  • @BryanOakley 关键字参数设计为函数配备可选关键字参数。如果您将函数定义为def foo(arg=DFLT),则预计有人会在某个时候调用foo(VALUE)foo(arg=VALUE)。在这种情况下,没有任何事情发生或可能永远发生,并且关键字参数仅用于将arg = VALUE的等价物注入@987654337的this实例@。这是一个聪明的技巧,而且肯定不是关键字参数的设计目的——而且不可能是这样,因为当时甚至不存在闭包。
猜你喜欢
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 2019-12-20
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 2014-08-15
相关资源
最近更新 更多