Python lambda 函数没有在 for 循环中正确调用[重复]

2024-05-03

我正在尝试使用 Python 中的 Tkinter 制作一个计算器。我使用 for 循环来绘制按钮,并且尝试使用 lambda 函数,以便仅在按下按钮时调用按钮的操作,而不是在程序启动时立即调用。然而,当我尝试这样做时,会抛出“列表索引超出范围”错误。

这是绘制按钮并设置其过程的相关部分:

# button layout
    #  (  )  AC **
    #  7  8  9  /
    #  4  5  6  *
    #  1  2  3  -
    #  0  .  =  +

    # list that holds the buttons' file names in order
    imgOrder = ["lpr", "rpr", "clr", "pow",
                "7", "8", "9", "div",
                "4", "5", "6", "mul",
                "1", "2", "3", "sub",
                "0", "dot", "eql", "add"];

    # list containing the actual values assigned to buttons in order
    charOrder = ["(", ")", "AC", "**",
                 "7", "8", "9", "/",
                "4", "5", "6", "*",
                "1", "2", "3", "-",
                "0", ".", "=", "+"];

    imgIndex = 0;

    for rowi in range(1, 6):
        for coli in range(4):
            
            # fetch and store the img
            img = PhotoImage(file="images/{}.gif".format(imgOrder[imgIndex]));
            # create button
            button = Button(self, bg="white", image=img,
                            borderwidth=0, highlightthickness=0, activebackground="white",
                            command=lambda: self.process(charOrder[imgIndex]));
            # set button image
            button.image = img;
            # put the button in its proper row and column
            button.grid(row=rowi, column=coli, sticky=N+S+E+W);

            imgIndex += 1;

    
    # pack the GUI
    self.pack(fill=BOTH, expand=1);

    
# processes button presses
def process(self, button):
    print("Button {button} pressed!");
    
    # AC clears the display
    if (button == "AC"):
        # clear
        self.display["text"] = "";

    # otherwise, the number/operator can be tacked on the end
    else:
        self.display["text"] += button;

具体来说,引发错误的行是带有 lambda 函数的行,但我不知道有什么方法可以只让按钮在单击时注册,而不需要单独为每个按钮写出此块。


这是一个典型的不必要的关闭案例。这是一个简化的示例:

funcs = []
for i in range(3):
    funcs.append(lambda: i + 1)
for func in funcs:
    print(func())

人们可能期望这会打印出来1 2 3,但它打印3 3 3反而。原因是,lambda is a closure,关闭变量i(在其上下文中捕获它)。当我们执行函数时,变量i保留在循环中的最后一个值(2)。重申一下,lambda不捕获value,但是variable。为了避免这种情况,我们要传递当前值i进入函数作为范围。为此,我们可以构造一个函数,它接受i作为参数,捕获范围进入闭包并返回我们想要的“定制”函数:

from functools import partial
funcs = []
for i in range(3):
    funcs.append((lambda val: lambda: val + 1)(i))
for func in funcs:
    print(func())

等价地,我们可以使用functools.partial,它就是这样做的:

from functools import partial
funcs = []
for i in range(3):
    funcs.append(partial(lambda val: val + 1, i))
for func in funcs:
    print(func())

Here, lambda val: val + 1需要一个参数;partial(lambda val: val + 1, 0)将产生一个新函数,其中第一个参数固定为0- 基本上,lambda: 0 + 1。这不会捕获任何变量,从而避免您遇到的问题。

tl;dr:

command=partial(lambda i: self.process(charOrder[i]), imgIndex)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python lambda 函数没有在 for 循环中正确调用[重复] 的相关文章

随机推荐

  • 指定 purecss 网格的折叠顺序

    我想要一个 purecss 网格 当它折叠时 即较小屏幕上的断点 是否可以使右侧网格项出现在左侧网格项之前 即某种崩溃命令 我相信使用 Flexbox 模型可以实现这些目标 但我不是这方面的专家 所以非常感谢指导 Thanks PureCS
  • 返回 const std::string 真的比非 const 慢吗?

    在另一个问题中 用户评论说返回 const std string 会损失移动构造效率并且速度更慢 分配此方法的返回字符串真的是这样吗 const std string toJson const std string someText con
  • Excel:如何通过VBA搜索电子表格1值是否存在于电子表格2中

    在电子表格 1 中 B 列包含值 即 V 9999 我正在尝试查看电子表格 2 的 B 列中是否存在这些值 我遇到的问题是 每次更新电子表格时数据都会发生变化 并且 B 列中的每行之间并不总是 1 1 匹配 例如 V 9999 可能存在于电
  • Azure 角色配置管理

    当您别无选择只能在 web config 或 app config 中保存配置设置时 我不明白 Windows Azure 如何让您改变应用程序的配置 例如 项目经常会使用大量使用 web config 的第三方库 web config 的
  • 如何读取未知数量的输入?

    我正在使用 C Primer 这本书学习 C In 第1 4 3节 给出了以下关于读取未知数量的输入的示例代码 include
  • 理解Python中的元类和继承[重复]

    这个问题在这里已经有答案了 我对元类有一些困惑 具有继承性 class AttributeInitType object def init self kwargs for name value in kwargs items setattr
  • 二维几何:如何检查点是否在角度内

    我有以下二维几何问题 我有一个点 从该点投射一个无限角度 2D 锥体 该角度由方向和角度给出 该点和方向形成一个向量 并且角度的每一侧一半形成 2D 锥体 现在我想检查 2D 中的另一个点是在这个圆锥体内部还是外部 如何才能实现这一目标 谢
  • 我可以采取什么方法使用 Web 技术开发桌面应用程序

    我想知道是否有任何方法可以创建一个作为桌面应用程序启动的应用程序 供个人使用 由于桌面应用程序可以使用我的 HDD 文件 我可能想要管理这些文件 但觉得将它们扔到网络服务器上并不安全 但我认为我将来可能想做的是将应用程序移植到网络上 因为我
  • WPF 数据绑定和级联转换器?

    我想知道使用 wpf 数据绑定时是否可以级联转换器 例如就像是
  • 预编译 Rails 5 以包含所有资源

    我正在尝试预编译所有资产以进行生产 当我跑步时RAILS ENV production bundle exec rake assets precompile并非我的所有资源都经过预编译 我尝试过使用其他人在其他类似问题中建议的方法 但它们对
  • 如何从主体上的 onClick 事件获取鼠标单击的绝对位置?

    我试图获取鼠标单击相对于浏览器 主体的绝对位置 顶部和左侧 not主体内的任何父元素 我有一个绑定到 body 的侦听器 但 e pageX 和 e pageY 为我提供了相对于 div 的位置 请注意 我可以利用 jQuery 和 YUI
  • 通过 Instagram API 访问公共 Instagram 内容,且 accesstoken 不会过期

    我想显示来自 Instagram 的与特定主题标签相关的公共内容 一切正常 但我无法更新access token每次过期的时候 不要假设您的 access token 永远有效 https www instagram com develop
  • ASP.NET中如何获取当前域名

    我想在asp net c 中获取当前域名 我正在使用这段代码 string DomainName HttpContext Current Request Url Host 我的网址是localhost 5858但它只返回localhost
  • ggplot geom_hline 中无法识别数据列

    我想知道为什么变量mean y不被我识别geom hline yintercept unique mean y call library tidyverse set seed 20 n groups lt 2 n in group lt 2
  • 为什么我们在Java中使用接口引用类型? [复制]

    这个问题在这里已经有答案了 我即将参加第一门面向对象编程课程的期末考试 但我仍然不明白多态性的概念 假设我有一个抽象类 Vehicle 该类有一个名为 Aircraft 的子类 我的问题是 这两个代码有什么不同 Aircraft Jetpl
  • Android SDK 中缺少 Gradle(使用 cordova + ionic)

    是的 我搜索了这个 但没有搜索到任何内容 只是有关 ANDROID HOME 路径的信息 但就我而言 我认为这不是真正的问题 当我尝试做的时候ionic build android我收到这个错误 错误 在 android sdk 中找不到
  • c# 错误:无法识别的配置部分 userSettings - 停止程序读取 user.config?

    在我的 C 表单应用程序 在 VS2010 中使用 NET 4 0 创建 中 我使用应用程序设置来存储输出路径 以前此设置是使用用户范围配置的 但我必须将其范围更改为应用程序 执行此操作后 我现在在表单启动时收到无法识别的配置部分 user
  • iOS:如何创建并绘制(并保存)大于屏幕的图像?

    我们正在创建一个 iOS 照片应用程序 为此 我们必须创建动态大小的图像 最大约为 2500x1600 像素 创建此图像后 我们希望以相当快的速度在大图像之上绘制较小的图像 正如我们所看到的 问题在于不可能获得大于屏幕分辨率的上下文 该调用
  • 如何将“从文件夹打开网站”转换为基于 csproj 的“ASP.NET Web 应用程序”项目

    标题几乎说明了一切 我有一个已构建并签入 vss 的 网站 要打开它 我们将文件 gt 打开 gt 网站 然后选择文件夹 这种技术可以让您获得一个项目 但没有 cs vb proj 文件 有没有简单的方法可以将其转换为 ASP NET We
  • Python lambda 函数没有在 for 循环中正确调用[重复]

    这个问题在这里已经有答案了 我正在尝试使用 Python 中的 Tkinter 制作一个计算器 我使用 for 循环来绘制按钮 并且尝试使用 lambda 函数 以便仅在按下按钮时调用按钮的操作 而不是在程序启动时立即调用 然而 当我尝试这