tkinter,在super()上传递* args * kwargs。__init __

时间:2019-03-16 06:33:03

标签: python tkinter

我会问为什么此代码有效

import tkinter as tk

class App(tk.Tk):

    def __init__(self, *args, **kwargs):            
        super().__init__()    
        print(args,kwargs)            
        self.title("Hello World")
        self.geometry("400x300")

if __name__ == '__main__':

    args = ('Y','Y','Z')
    kwargs = {'server':"127.0.0.1",'user':"guest",'passw':"12345",'database':"genbank"}    
    app = App(*args,**kwargs)

但是如果我代替

super().__init__()

super().__init__(*args, **kwargs)

那应该是正确的方法,它不起作用。

它返回

super().__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'passw'

有什么建议吗?

致谢

更新

在@Bryan Oakley注释之后,我想补充一些注意事项。

0)我了解到kwargs仅接受以下密钥默认值:

class tkinter.Tk(screenName = None,baseName = None,className ='Tk',useTk = 1)

import tkinter as tk

class App(tk.Tk):
    def __init__(self, *args, **kwargs):

        print("my __init__  args {}".format(args))
        print("my __init__  kwargs {}".format(kwargs))

        try:
            super().__init__(*args, **kwargs)
        except:
            args = ()
            super().__init__(*args, **kwargs)

        print("my super args {}".format(args))
        print("my super kwargs {}".format(kwargs))

        self.title("Hello World")
        self.geometry("400x300")

if __name__ == '__main__':

    args = ('x','y','z')
    kwargs = {'baseName':'foo','className':'bar'}

    app = App(*args,**kwargs)

返回

  

我的 init 参数('x','y','z')

     

我的 init kwargs {'baseName':'foo','className':'bar'}

     

我的超级参数()

     

我的超级拳头{'baseName':'foo','className':'bar'}

1)但是参数?

在有Windows OS的工作环境中,我可以通过args,在linux,debian 9上,它返回

一个错误,为此,我提出了例外,例如:

_tkinter.TclError:无法连接以显示“ x”

很抱歉对此如此密集,但我还没有真正明白。

5 个答案:

答案 0 :(得分:1)

使用super().__init__(*args, **kwargs)的代码版本不起作用,因为您的父类(tkinter.Tk)不支持您要传递的参数。

我不清楚您究竟希望这些论点做什么。它们不是tkinter通常关心的东西,因此无需将其继续下去。如果它们是您的班级确实关心的事情,则可能要明确地将它们命名为参数,而不是使用*args**kwargs

答案 1 :(得分:0)

super().__init__()初始化App,的超类,即tk.Tk。调用App(*args,**kwargs)时,您通过kwargs将命名参数tk.Tk()传递给super().__init__(*args, **kwargs)'passw'无法识别参数(tk.Tk())中的至少一个。实际上,它们都不被识别,但是第一个无法识别会导致程序崩溃。

答案 2 :(得分:0)

考虑以下代码:

kwargs = {'server':"127.0.0.1",'user':"guest",'passw':"12345",'database':"genbank"}    
app = App(*args,**kwargs)

在功能上与此相同:

app = App(server="127.0.0.1", user="guest", passw="12345", database="genbank")

现在考虑以下代码行:

super().__init__(*args, **kwargs)

super()返回基类,在这种情况下为Tk。因此,您的代码在功能上与此等效:

Tk(server="127.0.0.1", user="guest", passw="12345", database="genbank")

由于server类不支持userpasswdatabaseTk,因此会引发错误。

解决方案是确保在调用super().__init__时仅将有效的选项传递给超类。对于您的类来说,接受这些选项并对其进行任何操作都很好,但是您不应该将这些参数传递给超类。

答案 3 :(得分:0)

我使讨论重新进行,因为我将找到一种方法来完成我想要的工作,即在启动tkinter脚本时将大量任意args或kwargs传递给类。

看看这个脚本,App类从Tk继承而来,但是在启动时会收到列表,args和dict,kwargs

  

args =('Y','Y','Z')

     

kwargs = {'passw':'12345','user':'guest','server':'127.0.0.1','database':'genbank'}

     

app = App(* args,** kwargs)

     

app.mainloop()

import tkinter as tk

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        super(App, self).__init__()

        print("args type: {}".format(type(args)))
        for i in args:
            print(i)

        print("kwargs type: {}".format(type(kwargs)))
        for k, v in kwargs.items():
            print(k,v)

        self.title("Hello World")
        self.geometry("400x300")

if __name__ == '__main__':

    args = ('Y','Y','Z')
    kwargs={'passw': '12345', 'user': 'guest', 'server': '127.0.0.1','database': 'genbank'}
    app = App(*args, **kwargs)
    app.mainloop()

答案 4 :(得分:0)

https://docs.python.org/3/library/tkinter.html#tkinter.Tk上的函数定义可以看出, class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=1),它不支持您传递给它的任何 kwargs。

我建议


import tkinter as tk

class App(tk.Tk):

    def __init__(self, *args, **kwargs):
        
        # Pop and store your kwargs into variables of the class
        # Make sure to pop out all your defined keys in kwargs as below
        self._server = kwargs.pop('server')
        self._user = kwargs.pop('user')  
        self._password = kwargs.pop('passw')  
        self._database = kwargs.pop('genbank')    
        
        # And pass the args and kwargs
        super().__init__(*args, **kwargs)  
            
        self.title("Hello World")
        self.geometry("400x300")

if __name__ == '__main__':

    args = ('Y','Y','Z')
    kwargs = {'server':"127.0.0.1",'user':"guest",'passw':"12345",'database':"genbank"}    
    app = App(*args,**kwargs)