这是我从别人那里收到的一些代码,为什么需要 **kwargs?

This is some code I received from someone else, why is **kwargs needed?

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class CheckboxRow(tk.Frame):
    def __init__(self, master, name, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        self.name = name

        checkbox = tk.Checkbutton(self, text=name)
        checkbox.pack(side=tk.LEFT)

        deleteItem = tk.Button(self, text="x", bg="red", fg="white",
                                activebackground="white", activeforeground="red",
                                command=self.destroyCheckbox)
        deleteItem.pack(side=tk.RIGHT)

    def destroyCheckbox(self):
        self.master.master.checkboxList.remove(self.name)
        self.destroy()

class CheckboxArea(tk.Frame):
    def add(self, name):
        row = CheckboxRow(self, name)
        row.pack(fill=tk.X)

class InputStuff(tk.Frame):
    def __init__(self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

        prompt = tk.Label(self, text="What do you want your checkbox to be for?")
        prompt.pack()

        bottomInput = tk.Frame(self)
        self.entry = tk.Entry(bottomInput, bd=3)
        self.entry.pack(side=tk.LEFT)
        buttonConfirm = tk.Button(bottomInput, text="Confirm", command=self.drawCheckbox)
        buttonConfirm.pack(side=tk.LEFT)
        bottomInput.pack()

        buttonDone = tk.Button(self, text = "Close Input", command=master.hide_input_stuff)
        buttonDone.pack()

    def drawCheckbox(self, event=None):
        self.master.add(self.entry.get())
        self.entry.delete(0, tk.END)

class MainWindow(tk.Frame):
    def __init__(self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        master.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.checkboxList = []

        self.checkbox_area = CheckboxArea(self)
        self.checkbox_area.pack(fill=tk.X)

        self.input_stuff = InputStuff(self)
        self.add_button = tk.Button(self, text="Add Item", command=self.show_input_stuff)

        self.hide_input_stuff() # start with "add" button active

        self.load()

    def add(self, name):
        self.checkbox_area.add(name)
        self.checkboxList.append(name)

    def show_input_stuff(self):
        self.add_button.pack_forget()
        self.input_stuff.pack()
        self.input_stuff.entry.focus()
        self.master.bind('<Return>', self.input_stuff.drawCheckbox)

    def hide_input_stuff(self):
        self.input_stuff.pack_forget()
        self.add_button.pack()
        self.master.unbind('<Return>')

    def load(self):
        try:
            with open('toDoListSaveFile.json') as infile:
                checkboxList = json.load(infile)
            for savedCheckbox in checkboxList:
                self.add(savedCheckbox)
        except (IOError, ValueError):
            #an error occured while loading ... so no saved settings loaded
            pass

    def on_closing(self):
        with open("toDoListSaveFile.json", 'w') as outfile:
            json.dump(self.checkboxList, outfile)
        self.quit()

def main():
    master = tk.Tk()
    master.title("To-Do List (with saving!)")
    master.geometry("300x300")
    win = MainWindow(master)
    win.pack(fill=tk.X)
    master.mainloop()

if __name__ == '__main__':
    main()

**kwargs 在 class CheckboxRow 中。为什么需要它?据我所知,当你接受可变数量的参数时你只需要 **kwargs,但是 __init__() 只会接受三个参数,self,masterandname`。

tk.Frame.__init__。为什么这里需要 kwargs?我很确定我应该如何使用 kwargs 是错误的,有人可以解释一下吗?

严格来说,不需要。但是,通过包含它,您可以将标准框架选项传递给 subclasses.

例如,使用 **kwargs,您可以像这样设置框架的边框宽度:

x = CheckboxRow(root, "A row", borderwidth=1, relief="sunken")

原因是,borderwidth=1, relief="sunken" 包含在 kwargs 中,它被传递给继承的 Frame class,它将接受这些参数。

如果您还从对 Frame.__init__ 的调用中删除 **kwargs,则可以从参数列表中省略它,缺点是您无法再传递有效的 Frame 选项:

class CheckboxRow(tk.Frame):
    def __init__(self, master, name):
        tk.Frame.__init__(self, master)
class CheckboxRow(tk.Frame):
    def __init__(self, master, name, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

这样,任何用于初始化 CheckboxRow 实例的关键字都将:

  • 被录取
  • 被传给初始化一个tk.Frame

查看您的代码,不查看 documentation.

就不可能知道 tk.Frame 将使用哪些关键字参数

这是一个没有 kwargs 的更简单的例子:

def f(x):
    print x

f(2, width=800, height=600)
#=> TypeError: f() got an unexpected keyword argument 'width'

kwargs:

def f(x, **kwargs):
    print x
    g(**kwargs)

def g(**kwargs):
    print kwargs

f(2, width=800, height=600)
# 2
# {'width': 800, 'height': 600}

kwargs 允许您传递可选的关键字参数。因此,如果您只想更改某些参数而不更改其他参数:

例如:

f = Frame(height=2, bd=1, relief=SUNKEN)
f = Frame(relief=SUNKEN) #This also works
f = Frame() # Also works