Um den Unterschied in der Verwendung von Methodenaufrufen zu verstehen, schrieb ich eine MVC in Python 2.7. Hier ist der Code:Python - Unterschied zwischen self.method, Lambda: self.method() und self.method() beim Start
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()
Wenn man es ausführt und trifft auf die Schaltfläche, um die Etiketten zu aktualisieren, ist das Ergebnis folgendes:
Wie man sehen kann, ist model.self.data["Value_One"]
nicht festgelegt auf Start, wegen der Verwendung von lambda
, die ich für eine namenlose Funktion hielt, die nur einen Wert und nichts mehr zurückgeben kann. Hier scheint es den ersten Aufruf der Methode durch die Befehlszeile der Schaltfläche set_v_one
zu verhindern.
Bei model.self.data["Value_Two"]
wird der Wert beim Start aktualisiert. Ich denke, das ist, weil die Funktion aufgerufen wird, wenn die Befehlszeile der Schaltfläche gelesen wird und die Schaltfläche aufgrund des aktiven Aufrufs oder der Initialisierung der Methode über die Brakets ()
erstellt wird, da dies auch dann geschieht, wenn dies nicht der Fall ist pack den Knopf ein.
Für model.self.data["Value_Three"]
wird der Wert auch beim Start nicht aktualisiert. Dies ist, wie ich denke, durch die Methode set_value_three(self)
des Controllers an die Befehlszeile gebunden, aber nicht initialisiert, aufgrund des fehlenden Aufrufs dafür durch die Verwendung der Brakets ()
.
Nach Drücken der Tasten set_v_one
und set_v_three
, erhalten die Werte korrekt aktualisiert, wie durch die entsprechenden Etiketten angegeben label_one
und label_three
.
Auch wenn ich diese Methodenaufrufe oft nutze, konnte ich noch nicht ganz verstehen, wie sie im Detail arbeiten. Wenn jemand das klären könnte oder mich auf eine gute Quelle verweisen könnte, die ich noch nicht gefunden habe, würde es sehr geschätzt werden.
'self.method <- Referenz auf die Methode', 'self.method() <- Methode aufrufen. Sie können auch 'self.method' verwenden, wenn Sie' lambda: self.method() 'verwenden, da das Lambda es nur aufrufbar macht. –