用lambda函数右击Tkinter中的赋值问题

2024-10-01 00:19:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个相当复杂的tkintergui,所以避免重复使用lambda函数分配控件是值得的。代码摘录如下:

    def createRightMenu(self, treeName, commands: []):
       for cmd in commands:
          self.rightMouse[treeName].add_command(label= cmd['label'], command= lambda: self.execCommand(cmd['reqId']))
       self.tree[treeName].bind("<Button-3>", lambda event: 
       self.rightMouse_click(event.x_root, event.y_root, treeName))

    def execCommand(self, reqId):
       print("execCommand", reqId)

    self.tree = {}
    treeName = 'a'
    self.createTree(root, treeName)
    self.createRightMenu(treeName , [
        {'label': 'copy', 'reqId': 1},
        {'label': 'retrieve', 'reqId': 2},
        ])

什么有用? 在我的右击菜单中,我得到“copy”和“retrieve”两个条目,并调用execCommand

什么不起作用? execCommand总是获取最后一个列表元素,即“retrieve”,2作为参数,即使我右键单击“copy”。如果我手动添加两个。add\u命令就可以了。只使用for循环是行不通的。知道为什么吗


Tags: lambdaselfcmdeventfordefrootlabel
1条回答
网友
1楼 · 发布于 2024-10-01 00:19:20

作用域问题:当lambda激发时,它检查cmd变量的作用域。在for cmd in commands:的每次迭代过程中,cmd变量被设置为一个新值。在迭代结束时,中的cmd变量仍然等于for cmd in commands:的最终迭代(即-{'label': 'retrieve', 'reqId': 2}

解决方案是在lambda的签名中指定一个“new”变量,然后根据python中作用域的工作方式使用它(在“new”上加引号,因为它可以是同名的变量)。具体来说,您可以将代码更改为:

for cmd in commands:
    self.rightMouse[treeName].add_command(label= cmd['label'],
                                          command= lambda reqid = cmd['reqId']: self.execCommand(reqid))

下面是一个脚本,通过示例演示我在这里所说的内容:

lambdas = []
words = ["Hello","World"]
print("Creating Lambds")
for word in words:
    my_lambda = lambda: word
    print('>>> Result for "{}" lambda: "{}"'.format(word,my_lambda()))
    lambdas.append(my_lambda)

print("Post Loop Lambda Results")
for w,_lambda in zip(words,lambdas):
    print('>>> Result for "{}" lambda: "{}"'.format(w,_lambda()))

word = "Foobar"
print('Setting word variable to "{}"'.format(word))
print("New Results for lambdas:")
for w,_lambda in zip(words,lambdas):
    print('>>> Result for "{}" lambda: "{}"'.format(w,_lambda()))

print("        \nSolution:\n")
lambdas = []
words = ["Hello","World"]
print("Creating Lambds")
for word in words:
    my_lambda = lambda myword = word: myword
    print('>>> Result for "{}" lambda: "{}"'.format(word,my_lambda()))
    lambdas.append(my_lambda)

print("Post Loop Lambda Results")
for w,_lambda in zip(words,lambdas):
    print('>>> Result for "{}" lambda: "{}"'.format(w,_lambda()))

word = "Foobar"
print('Setting word variable to "{}"'.format(word))
print("New Results for lambdas:")
for w,_lambda in zip(words,lambdas):
    print('>>> Result for "{}" lambda: "{}"'.format(w,_lambda()))

以下是一些链接:

相关问题 更多 >