【问题标题】:Double-lambda Python双 lambda Python
【发布时间】:2017-02-08 18:30:20
【问题描述】:

在一个 lambda 中执行多个语句是否可行?我的控制器中的app_data 字典有一个属性“listbox”,用于存储选定的列表框值。 SelectPage 上的按钮有一个 lambda 命令,可将帧更改为 NextPage

frame switch 和 app_data set 语句可以出现在双 lambda 中吗?如果是这样,这会是什么样子?还是这些操作必须单独发生(即在按钮单击事件中)?

更新 #1:

问题与 lambda 表达式无关,因为仅在 .set(1) 中添加一个常量(即 1)也不会保存。

更新 #2: 使用带有 doStuff(controller) 的 lambda 可以在一定程度上解决问题,但列表框引用会引发错误:

值 = self.listbox.get(self.listbox.curselection()) AttributeError: 'SelectPage' 对象没有属性 'listbox'

按钮:

   button1 = ttk.Button(self, text='Next Page',
                         command=lambda:self.doStuff(controller))

doStuff():

    def doStuff(self,controller):
        controller.show_frame(NextPage)
        controller.app_data["listbox"].set(1)
        value = self.listbox.get(self.listbox.curselection())
        print(value)
        print("do Stuff successful")

完整代码:

from tkinter import *
from tkinter import ttk



class MyApp(Tk):
    # Controller class
    def __init__(self):
        Tk.__init__(self)

        # App data in controller
        self.app_data = {"listbox":    StringVar(),
                         "entry":       StringVar(),
                         }

        container = ttk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        self.frames = {}
        for F in (SelectPage, NextPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky = NSEW)
        self.show_frame(SelectPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def get_page(self,classname):
        for page in self.frames.values():
            if str(page.__class__.__name__) == classname:
                return page
        return None

class SelectPage(ttk.Frame):

    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        ttk.Label(self, text='Select Page').grid(padx=(20,20), pady=(20,20))

        listbox = Listbox(self,exportselection=0)
        listbox.grid()
        for item in [0,1,2,3,4,5]:
            listbox.insert(END, item)
            print (item)
        entry1 = ttk.Entry(self, textvariable=self.controller.app_data["entry"], width=8)
        entry1.grid()
        button1 = ttk.Button(self, text='Next Page',
                          command=lambda:self.doStuff(controller)) # something like this lambda concept
        button1.grid()

    def doStuff(self,controller):
        controller.show_frame(NextPage)
        controller.app_data["listbox"].set(1)
        value = self.listbox.get(self.listbox.curselection())
        print(value)
        print("do Stuff successful")

class NextPage(ttk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        ttk.Frame.__init__(self, parent)
        ttk.Label(self, text='Next Page').grid(padx=(20,20), pady=(20,20))
        button1 = ttk.Button(self, text='Select Page',
                             command=lambda: controller.show_frame(SelectPage))
        button1.grid()
        button2 = ttk.Button(self, text='press to print', command=self.print_it)
        button2.grid()

    def print_it(self):

        value = self.controller.app_data["listbox"].get()
        print ('The value stored in StartPage some_entry = ' + str(value))
        value = self.controller.app_data["entry"].get()
        print ('The value stored in StartPage some_entry = ' + str(value))
app = MyApp()
app.title('Multi-Page Test App')
app.mainloop()

【问题讨论】:

  • 不要使用 lambda,使用 def 的适当函数。注意:您可以在函数中定义函数,并在必要时使用它们的本地命名空间。
  • 你尝试的时候发生了什么?您的代码是否按预期工作?
  • @Goyo 代码运行,但列表框项目未保存
  • 更简单:def doStuff() 里面有语句,然后是command=doStuff。注意:doStuff,而不是 doStuff()

标签: python lambda tkinter


【解决方案1】:

您原来的lambda 不起作用,因为show_frame(...) 返回None,这会使and 短路,因此剩余的表达式不会执行。只需将其更改为or。由于事件调用者不关心您返回的内容,您还可以为两个子表达式创建两个项目tuple。还有其他问题,比如self.listbox不存在,我修复了,但其他问题仍然存在。

撇开迂腐不谈,lambda 只接受表达式,它是语句的子集。

self.listbox = listbox
button1 = ttk.Button(self, text='Next Page',
                  command=lambda: controller.show_frame(NextPage) or self.controller
                     .app_data["listbox"]
                     .set(self.listbox.get(self.listbox.curselection()))) # something like this lam

【讨论】:

    【解决方案2】:

    在一个 lambda 中执行多条语句是否可行?

    没有。一般来说,您应该完全避免使用 lambda,并且当您必须使用它时,您需要使其尽可能简短。如果您需要调用多个函数,请创建一个调用其他函数的新函数。

    此外,如果您传入的参数只是对象的一个​​属性,则根本不需要 lambda。我认为下面的代码更容易阅读、更容易理解、更容易编写,因此也更容易维护:

    button1 = ttk.Button(self, text='Next Page',command=self.doStuff)
    ...
    def doStuff(self):
        self.controller.show_frame(NextPage)
        self.controller.app_data["listbox"].set(1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      • 2011-12-19
      • 2012-01-15
      • 2021-10-11
      • 2018-06-07
      相关资源
      最近更新 更多