为什么我的函数需要一个参数以及如何用+不调用它?

Why does my function need an argument and how to call it with+without?

我这里有一个神奇的功能:

def update_config(val):
    config = configparser.ConfigParser()
    fonts_comb = ""
    for i in range(len(fonts)):
        if i == len(fonts) - 1:
            fonts_comb = fonts_comb + fonts[i]
        else:
            fonts_comb = fonts_comb + fonts[i] + ", "
    config["LISTS"] = {"Fonts": fonts_comb}
    config["variables"] = {"font_size": (screen_font_size.var).get(),
                           "x_offset": (x_offset_spin.var).get(),
                           "y_offset": (y_offset_spin.var).get(),
                           "language": language,
                           "preview_font_size": (preview_font_size_spin.var).get()}
    variables = config["variables"]
    if (fonts_menu.var).get() != strings[17]:
        variables["font"] = (fonts_menu.var).get()
    else:
        variables["font"] = font
    if (preview_fonts.var).get() != strings[18]:
        variables["preview_font"] = (preview_fonts.var).get()
    else:
        variables["preview_font"] = preview_font
    with open("config.ini", "w") as configfile:
        config.write(configfile)

我也不知道它是否相关,但基本上它的功能如其名 - 更新配置文件。
我不喜欢这个函数的地方在于它需要一个参数(这里的 val,也许应该是 self?)。因为它需要那个参数,所以我不能称它为 "properly"。让我演示一下,以下工作正常:

class OptionMenus(tk.OptionMenu):
    def __init__(self, master, status, *fonts):
        self.var = tk.StringVar(master)
        (self.var).set(status)
        (tk.OptionMenu).__init__(self, master, self.var, *fonts,
                                 command = update_config)

但是 - 像下面这样调用 returns 这个错误:TypeError: update_config() takes 0 positional arguments but 1 was given

class Spinboxes(tk.Spinbox):
    def __init__(self, master):
        self.var = tk.IntVar()
        tk.Spinbox.__init__(self, master, textvariable = self.var,
                            from_ = 0, to = 100, command = update_config)

现在,我已经用这个解决了:

def crossover():
    val = ""
    update_config(val)

但这似乎是一种猴子般的做事方式,那么有没有更好的方法来调用该函数?

使用默认参数值:

def update_config(val=None):
    # etc.

您也可以完全删除参数并使用单个参数 lambda 在必须传递参数的上下文中调用它:

def update_config():
    # etc.

# ...

tk.OptionMenu.__init__(self, master, self.var, *fonts,
                       command=lambda _: update_config())

不过我觉得第一种比较简单

  1. update_config 看起来像一个实例方法,所以是的,我建议使用接受的变量 self.
  2. 如果错误说它需要 0 个参数但给出了 1 个参数,这就是它所说的。这意味着从 Spinbox 对象调用 update_config 会向它传递一个参数。但是,由于它从 OptionMenus 开始工作正常,因此无需参数即可工作,因此您需要将其设置为处理可选参数。

变化:

def update_config(val):

至:

def update_config(self, event=None):

这应该可以解决问题。