簡體   English   中英

tkinter,在 super().__init__ 上傳遞 *args *kwargs

[英]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類不支持serveruserpasswdatabase ,因此會引發錯誤。

解決方案是確保在調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM