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.