[英]tkinter, passing *args *kwargs on super().__init__
我會問為什么這段代碼有效
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)
那個回報
我的初始化參數('x'、'y'、'z')
我的init kwargs {'baseName': 'foo', 'className': 'bar'}
我的超級 args ()
我的超級 kwargs {'baseName': 'foo', 'className': 'bar'}
1)但是args?
在我有 Windows 操作系統的工作中,我可以傳遞 args,在 linux、debian 9 上,它返回
一個錯誤,為此我提出了例外,例如:
_tkinter.TclError: 無法連接以顯示“x”
我很抱歉在這方面如此密集,但我還沒有真正理解它。
帶有super().__init__(*args, **kwargs)
的代碼版本不起作用,因為您的父類( tkinter.Tk
)不支持您傳遞的參數。
我不清楚你期望這些論點做什么,確切地說。 它們不是tkinter
通常關心的事情,所以沒有必要傳遞它們。 如果它們是您的類確實關心的事情,您可能希望將它們顯式命名為參數,而不是使用*args
和**kwargs
。
super().__init__()
初始化App,
的超類App,
即tk.Tk
。 當您調用App(*args,**kwargs)
,您通過super().__init__(*args, **kwargs)
將命名參數kwargs
傳遞給tk.Tk()
super().__init__(*args, **kwargs)
。 tk.Tk()
無法識別至少其中一個參數 ( 'passw'
tk.Tk()
。 實際上,它們都沒有被識別,但是第一個未被識別會導致程序崩潰。
考慮這個代碼:
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")
由於Tk
類不支持server
、 user
、 passw
和database
,因此會引發錯誤。
解決方案是確保在調用super().__init__
時只將有效選項傳遞給超類。 您的類可以接受這些選項並用它們做任何它想做的事情,但是您不應該將這些參數傳遞給超類。
我重新討論這個問題,因為我會找到一種方法來做我想做的事情,即在我們啟動 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().__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()
從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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.