Чтобы понять разницу в использовании вызовов методов, я написал MVC в python 2.7. Вот код:Python - разница между self.method, lambda: self.method() и self.method() при запуске
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"]
значение обновляется при запуске. Я думаю, это потому, что функция вызывается, когда командная строка кнопки считывается и создается кнопка из-за активного вызова или инициализации метода с помощью команд ()
, потому что это происходит, даже если никто не делает этого упакуйте кнопку.
Для model.self.data["Value_Three"]
значение также не обновляется при запуске. Это, как я думаю, вызвано методом set_value_three(self)
контроллера, связанным с командной строкой, но не инициализированным из-за отсутствия вызова для него с помощью команд ()
.
После нажатия кнопки set_v_one
и set_v_three
значения получают правильно обновляется, как указано соответствующими этикетками label_one
и label_three
.
Несмотря на то, что я использую этот метод много, я еще не мог полностью понять, как они работают в деталях. Если кто-то может прояснить это или указать мне на хороший источник, которого я просто еще не нашел, это было бы очень признательно.
'self.method <- ссылка на метод',' self.method() <- вызов метода'. Вы также можете использовать 'self.method', если вы используете' lambda: self.method() ', поскольку лямбда просто делает его вызываемым. –