我会问为什么此代码有效
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”
很抱歉对此如此密集,但我还没有真正明白。
答案 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
类不支持user
,passw
,database
和Tk
,因此会引发错误。
解决方案是确保在调用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)