LoginSignup
0
2

More than 3 years have passed since last update.

Python 可変引数定義されたクラスを継承するときの覚書

Last updated at Posted at 2020-07-15

PythonのGUI(Tkinter)を使ってプログラムを書いていると、GUI Class継承する場合に
もれなく可変引数も継承されます。
しかし、継承先のClassで引数を追加すると、継承元でエラーが発生して使いづらい状況です。

例えば、TkinterのCheckbuttonは初期値を設定する事ができません。
初期値を設定できるようなCheckbuttonを作った際の覚書。

普通に記述すると、下記のようになります。

NormalCheckbox
cv = tk.BooleanVar()
cb = tk.Checkbutton(self, parent, variable=cv)
cv.set(True)  #初期値設定

しかし、私はこういう風に書きたい。

ShimplCheckbox
cb = tk.Checkbutton(self, parent, check=True)

そこで、tk.Checkbuttonを継承して、SimpleCheckを作ってみます

SimpleCheckbox.py
# Initial value = check=True or False
class SimpleCheck(tk.Checkbutton):
    def __init__(self, parent, *args, **kw):
        self.flag = kw.pop('check')
        self.var =  tk.BooleanVar()
        if self.flag:
            self.var.set(True)
        self.txt = kw["text"]
        tk.Checkbutton.__init__(self, parent, *args, **kw, variable=self.var)

    def get(self):
        return self.var.get()

しかし、このコードには問題があります。
それは、引数"check"を指定しなければエラーが発生するという問題です

mainloop
if __name__ == '__main__':
    app  = tk.Tk()
    sc1 = SimpleCheck(app, check=True, text="hoge")
    sc1.pack()
    sc2 = SimpleCheck(app)
    sc2.pack()

    print(sc1.getText())    
    print(sc1.cget('text'))#same result
    app.mainloop()
error
Traceback (most recent call last):
  File "arg_test.py", line 24, in <module>
    sc2 = SimpleCheck(app)
  File "arg_test.py", line 7, in __init__
    self.flag = kw.pop('check')
KeyError: 'check'

そこで可変引数を使った継承における、引数の取り出し方法を覚書として示す。
Check.png
三項演算子を使った場合、"pass"を使うとエラーが出るようです。

SimpleCheck.py
import tkinter as tk

# Check value  :check=True or False (Default False)
# Label text   :text=Keword
class SimpleCheck(tk.Checkbutton):
    def __init__(self, parent, *args, **kw):
        self.flag = kw.pop('check') if('check' in kw) else False
        self.txt  = kw['text']      if('text' in kw) else ""
        self.var =  tk.BooleanVar()
        if self.flag:
            self.var.set(True)
        tk.Checkbutton.__init__(self, parent, *args, **kw, variable=self.var)

    def get(self):
        return self.var.get()

    def getText(self):
        return self.txt

if __name__ == '__main__':
    app  = tk.Tk()
    sc1 = SimpleCheck(app, check=True, text="hoge")
    sc1.pack()
    sc2 = SimpleCheck(app)
    sc2.pack()

    print(sc1.getText())    
    print(sc1.cget('text'))#same result
    app.mainloop()

追記@shiracamusさんからアドバイス頂きまして
三項演算子を使わなくてもDicのpop第二引数で初期値を設定できるようです。
アドバイスありがとうございました。

diff
    def __init__(self, parent, *args, **kw):
        self.flag = kw.pop('check', False)
        self.txt  = kw['text']  if('text' in kw) else ""

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2