为了理解方法调用的使用差异,我在python 2.7中编写了一个MVC。这是代码:
import Tkinter as tk
class Model(object):
def __init__(self, *args, **kwargs):
# dict
self.data = {}
# -- >values
self.data["Value_One"] = tk.IntVar()
self.data["Value_Two"] = tk.IntVar()
self.data["Value_Three"] = tk.IntVar()
# --> texts
self.data["Text_Label_val_One"] = tk.StringVar()
self.data["Text_Label_val_Two"] = tk.StringVar()
self.data["Text_Label_val_Three"] = tk.StringVar()
class Control(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs) # init
tk.Tk.wm_title(self, "Testing Grounds") # title
self.model = Model()
self.view = View(parent = self, controller = self)
self.view.pack(fill = 'both', expand = True)
def set_labels_text(self):
self.model.data["Text_Label_val_One"].set("Value_One is set to: {0}".format(self.model.data["Value_One"].get()))
self.model.data["Text_Label_val_Two"].set("Value_Two is set to: {0}".format(self.model.data["Value_Two"].get()))
self.model.data["Text_Label_val_Three"].set("Value_Three is set to: {0}".format(self.model.data["Value_Three"].get()))
def set_value_one(self):
self.model.data["Value_One"].set(1)
def set_value_two(self):
self.model.data["Value_Two"].set(2)
def set_value_three(self):
self.model.data["Value_Three"].set(3)
class View(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.buttons()
self.labels()
def buttons(self):
set_v_one = tk.Button(self, text = "Set Value One To 1", command = lambda: self.controller.set_value_one())
set_v_one.pack(fill = 'x', expand = True)
set_v_two = tk.Button(self, text = "Set Value Two To 2", command = self.controller.set_value_two())
set_v_two.pack(fill = 'x', expand = True)
set_v_three = tk.Button(self, text = "Set Value Three To 3", command = self.controller.set_value_three)
set_v_three.pack(fill = 'x', expand = True)
update_lbl_two = tk.Button(self, text = "Update Labels", command = self.controller.set_labels_text)
update_lbl_two.pack(fill = 'x')
def labels(self):
label_one = tk.Label(self, textvariable = self.controller.model.data["Value_One"])
label_one.pack(fill = 'x', expand = True)
label_two = tk.Label(self, textvariable = self.controller.model.data["Value_Two"])
label_two.pack(fill = 'x', expand = True)
label_three = tk.Label(self, textvariable = self.controller.model.data["Value_Three"])
label_three.pack(fill = 'x', expand = True)
label_val_one = tk.Label(self, textvariable = self.controller.model.data["Text_Label_val_One"])
label_val_one.pack(fill = 'x', expand = True)
label_val_two = tk.Label(self, textvariable = self.controller.model.data["Text_Label_val_Two"])
label_val_two.pack(fill = 'x', expand = True)
label_val_three = tk.Label(self, textvariable = self.controller.model.data["Text_Label_val_Three"])
label_val_three.pack(fill = 'x', expand = True)
if __name__ == "__main__":
app = Control()
app.mainloop()
如果执行它并点击按钮更新标签,结果如下:
正如我们所看到的,model.self.data["Value_One"]
未在启动时设置,因为使用了lambda
,我认为它是一个无名函数,它只返回一个值,而不是更多。这里似乎通过按钮set_v_one
的命令行禁止方法的初始调用。
在model.self.data["Value_Two"]
的情况下,该值在启动时更新。我认为这是因为函数被调用,当读取按钮的命令行并创建按钮时,由于活动调用或通过brakets ()
初始化该方法,因为它确实发生了,即使一个人没有包装按钮。
对于model.self.data["Value_Three"]
,该值在启动时也不会更新。正如我所想的那样,这是由绑定到命令行的控制器的set_value_three(self)
引起的,但由于没有通过使用brakets ()
来调用它而没有初始化
按下set_v_one
和set_v_three
按钮后,值会得到正确更新,相应的标签为label_one
和label_three
。
即使我使用这些方法调用很多,但我还不能完全理解它们的工作原理。如果有人能够澄清这一点或者指出一个我尚未找到的良好来源,那将非常感激。
答案 0 :(得分:2)
总而言之,这里没有任何谜团。
Button构造函数的命令参数采用回调,即按下按钮时将执行的函数。您可以对按钮1和3执行此操作。因此,当单击相应的按钮时,将调用函数(无论是lambda还是绑定方法)并更新标签。使用按钮2,您实际上执行设置第二个标签值的方法,并为命令参数分配该方法调用的结果(将为None)。据我所知,这违反了API,可能会导致错误。
总结一下,你的困惑似乎源于混合了一个函数(一个可以执行的对象)和它的调用(执行一个函数的动作)。