Paylaştığınız kod düzgün çalışıyor. Ancak benim demek istediğim, yazdığınız kod, nesne tabanlı programlama yaklaşımına pek benzemiyor.
Mesela aşağıdaki parantez içindeki tk.Tk'yı boşuna yazmışsınız. Onu silerseniz, hiç bir değişiklik olmadığını görürsünüz.
class Button(tk.Tk):
*args ve **kwargs**'ın ne anlama geldiğinden bahsedeyim:
Biz neden class Button(tk.Button): gibi bir ifade yazarız? Oluşturacağımız Button isimli sınıf, tk.Button'u miras alsın diye.
Bir tk.Button nesnesi oluşturduğumuzda parametreler kullanıyoruz değil mi? İşte bu kullanılan parametreleri oluşturacağımız Button sınıfında da kullanabilmek için bu *args ve **kwargs ifadelerini kullanırız.
Örnek:
import tkinter as tk
class Button(tk.Button):
def __init__(self):
super().__init__()
self.pack()
root = tk.Tk()
Button(master=root)
root.mainloop()
Yukarıdaki kod TypeError: __init__() got an unexpected keyword argument 'master' gibi bir hata almamıza neden olur. Çünkü master parametresi __init__ metoduna ait bir parametre değil.
Peki! master parametresini __init__ metoduna ekleyelim.
import tkinter as tk
class Button(tk.Button):
def __init__(self, master):
super().__init__()
self.pack()
root = tk.Tk()
frame = tk.Frame(master=root)
frame.pack()
Button(master=frame)
for child in frame.winfo_children():
print(child)
root.mainloop()
Bu kodları çalıştırdığımızda, Button nesnesinin ekrana yerleştirildiğini görürsünüz. __init__ metodunun master isimli bir parametresi var. Ama bu parametrenin, miras alınan sınıfın __init__ metodu üzerinde herhangi bir etkisi yok. Bu yüzden bu düğme tk.Frame widgetine değil, tk.Tk widgetine yerleştirildi.
Kodu biraz daha değiştirelim:
import tkinter as tk
class Button(tk.Button):
def __init__(self, master):
super().__init__(master=master)
self.pack()
root = tk.Tk()
frame = tk.Frame(master=root)
frame.pack()
Button(master=frame)
for child in frame.winfo_children():
print(child)
root.mainloop()
Yukarıdaki koda göre, Button sınıfının örnek yapıcı fonksiyonu master parametresini alıyor ve bu parametre, miras alınan tk.Button sınıfının master parametresinin değeri haline getiriliyor. Sonuç olarak, bu örnekteki print fonksiyonu, .!frame.!button yazısını ekrana yazdırır. Yani Button nesnesinin ebeveyn widgeti, tk.Frame widgeti olmuş.
Ancak biz hala tk.Button sınıfına ait bütün parametreleri Button sınıfı için kullanamıyoruz. Aşağıdaki koda bakın mesela:
import tkinter as tk
class Button(tk.Button):
def __init__(self, master):
super().__init__(master=master)
root = tk.Tk()
Button(master=root, text="hello")
root.mainloop()
Bu kodu çalıştırdığımız zaman TypeError: __init__() got an unexpected keyword argument 'text' şeklinde bir hata alırız.
O halde bizim text parametresini de yapıcı fonksiyonun parametresi haline getirmemiz gerekiyor.
import tkinter as tk
class Button(tk.Button):
def __init__(self, master, text):
super().__init__(master=master, text=text)
root = tk.Tk()
Button(master=root, text="hello")
root.mainloop()
Biz bir sınıftan miras alırken, miras aldığımız sınıfın __init__ metodundaki bütün parametreleri yazmamak için *args ve **kwargs ifadesini kullanırız.
*args: Argümanların hepsini temsil eder, bir tuple nesnesidir.
def f(a, b, c):
return a, b, c
def g(*args):
return args
**kwargs: Anahtar kelime argümanlarını (ön tanımlı argümanları) temsil eder, bir dict nesnesidir.
def f(a=1, b=2, c=3):
return a, b, c
def g(**kwargs):
return kwargs.values()
Button örneğimize tekrar gelelim, kodu aşağıdaki gibi değiştiriyorum:
import tkinter as tk
class Button(tk.Button):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
root = tk.Tk()
Button(master=root, text="hello")
root.mainloop()
Artık, tk.Button nesnesinin kaç tane argümanı ve anahtar kelime argümanı varsa hepsini Button sınıfından bir örnek oluşturmak istediğimizde kullanabiliriz.
super ifadesi de miras alınan sınıfın yerine kullanılır.
class Button(tk.Button):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
ile
class Button(tk.Button):
def __init__(self, *args, **kwargs):
tk.Button.__init__(self, *args, **kwargs)
aynı işlevi görür.