簡體   English   中英

Python-self.method,lambda之間的區別:啟動時self.method()和self.method()

[英]Python - difference between self.method, lambda: self.method() and self.method() on startup

為了理解使用方法調用的區別,我在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()

如果執行該命令並單擊按鈕以更新標簽,則結果如下:

在此處輸入圖片說明

可以看到,由於使用了lambda ,因此未在啟動時設置model.self.data["Value_One"] ,我認為這是一個無名函數,只能返回一個值,僅此而已。 在這里,似乎通過按鈕set_v_one的命set_v_one了方法的初始調用。

對於model.self.data["Value_Two"] ,該值在啟動時更新。 我認為那是因為在讀取按鈕的命令行並創建按鈕時調用了該函數,這是由於主動調用或通過剎車()初始化了該方法,因為它的確發生了,即使沒有這樣做也是如此。打包按鈕。

對於model.self.data["Value_Three"] ,該值也不會在啟動時更新。 我想這是由綁定到命令行的控制器的set_value_three(self)方法引起的,但是由於沒有使用brickts ()進行調用而未初始化,因此未初始化。

按下按鈕set_v_oneset_v_three ,值將正確更新,如相應的標簽label_onelabel_three

即使我經常使用這些方法調用,但我還無法完全了解它們的詳細工作原理。 如果有人可以澄清這一點或為我提供一個我還沒有找到的好消息來源,將不勝感激。

總而言之,這里沒有謎。

Button構造函數的command參數接受回調,即當按下按鈕時將執行的函數。 您可以對按鈕1和3進行此操作。因此,當單擊相應的按鈕時,將調用函數(即lambda或bound方法)並更新標簽。 使用按鈕2,您實際上執行的方法是設置第二個標簽的值,並將該方法調用的結果分配給命令參數(將為None)。 據我了解,這違反了API,可能會導致錯誤。

綜上所述,您的困惑似乎源於混淆了一個函數(一個可以執行的對象)及其調用(執行一個函數的動作)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM