OOP yapısında iki çeşit özel metot bulunur. Bunlardan biri '@classmethod' iken diğeri de '@staticmethod' şeklindedir. Bu ikisi üzerine (özellikle @staticmethod) aklıma pek bir örnek gelmediği için anlamanız biraz zor olabilir. Ancak konu ilerledikçe ve bunları kullandıkça daha da rahatlayacaksınızdır. Şimdi, @classmethod ile başlayalım.
@classmethodNormalde class içerisine metot tanımlarken direkt olarak def <isim>(self): diyoruz; biliyorsunuz. @classmethod tanımlamak için aşağıdaki gibi bir kullanım sağlıyoruz.

class yapısı içerisinde olmak koşuluyla @classmethod diyoruz ve hemen altına, gerekli olan metot neyse onu tanımlıyoruz. @classmethod yazdıktan sonra hemen altında bulunan metot, @classmethod olarak işleme alınır.
Dikkat ederseniz def isim(self): yazmak yerine def isim(cls): yazdım. Oradaki 'cls' ifadesi aslında 'class' kelimesinin kısaltılmışıdır. En başta class Computer şeklinde tanımladığımız class kelimesi ile karışmaması için cls şeklinde bir ifade geliştirmişler. Bu, self ile benzer bir iş yapar ve direkt olarak sınıfın kendisiyle ilgilendiğimizi anlatır. Yani bu fonksiyonun referansı, class yapısının kendisidir.
@classmethod ile tanımlanan metotlar sınıfın kendisiyle ilgili olduğu için bir instance çağırırken self.brand şeklinde çağıramayız. Bunun yerine metot içerisindeyken cls.brand, metot dışındayken Computer.brand şeklinde çağırmak zorundayız. Bu dediğimi bir örnek ile görelim.

Dikkat ederseniz, self ifadesinin altı çizildi ve computerCounter ifadesi mavi değil, beyaz. Zaten kodu çalıştırırsanız ya da imleci üzerine götürürseniz hata verdiğini göreceksinizdir. İşte, isim isimli metot cls argümanını aldığı için yani sınıfın tam olarak kendisiyle ilgilendiği için çağırma işlemini self yerine cls ile yapıyoruz. Bakalım.

Gördüğünüz gibi, sorun yok.
Şimdi, bu metodu silelim ve yenisini oluşturalım. Oluşturacağımız bu metot bize, computerCounter değişkeninin değerini versin. Önceki bölümden hatırlarsınız; bu değişken, oluşturulan her instance başına bir artıyordu.

@classmethod ifademi ekledim ve altına printCounter(cls) şeklinde bir metot tanımladım. İçerisine de Computer.computerCounter dedim. Bu noktada bunun neden cls.computerCounter olmadığını merak edebilirsiniz. Biz, cls ile class yapılarının aynı olduğundan, cls ifadesinin class yapısının kendisiyle ilgilendiğini biraz önce öğrendik. Dolayısıyla cls.computerCounter ve Computer.computerCounter aynı şeyi ifade edecektir.
Peki, bunu nasıl print edeceğiz?

Yine sınıfın adını çağırıp fonksiyonun ismini veriyoruz. Yani print(Computer.printCounter()) diyoruz. pc1, pc2 ve pc3 olmak üzere 3 adet instance olduğu için de sonuç 3 olarak geldi.
Bu metodu silelim ve yerine başka bir metot koyalım.

tellMe(cls) şeklinde bir class metot (@classmethod) oluşturdum ve içine, class değişkenlerini yazdıracak kodu yazdım. Sonrasında print(Computer.tellMe()) şeklinde bunu çalıştırdım ve çıktı gayet başarılı bir şekilde geldi.
Şimdi, örneğin nesnelerin brand özelliğine erişelim. Bakalım, bizi ne bekliyor?

cls.brand dedim ama AttributeError şeklinde bir hata aldım. Bu hata bize şunu diyor: "Özellik Hatası: Computer sınıfının brand diye bir özelliği yok". Neden böyle oldu?
Hatırlarsanız nesnelerin (instances) özelliklerine erişirken @classmethod falan demeden direkt olarak def isim(self) diyorduk ve oradaki self sayesinde hepsine erişim sağlayabiliyorduk. Ancak buradaki argüman self değil, cls Bunun, sınıfın kendisiyle ilgili olduğunu defalarca söyledim. Demek ki nesne özelliklerine erişirken normal def isim(self) diyoruz, class değişkenlerine erişirken ise @classmethod diyoruz.
"@classmethod ile tanımlanan her metot class yapısının kendisiyle alakalıdır".
@classmethod ile tanımlanan metotların bir diğer özelliğine bakalım.

Gördüğünüz gibi nesneleri yani instance yapılarını yorum satırına dönüştürdüm. Yani bunlar çalıştırılmayacak. Dolayısıyla hiç tanımlanmamış gibiler. Kısacası class yapısının herhangi bir nesnesi yok. Buna rağmen @classmethod ile tanımladığımız metodun çalıştığını ve bize bir sonuç döndürdüğünü görüyorsunuz. Yani class yapınız içerisinde sadece class değişkenleri ile oynamak istiyorsanız, class yapısının tamamını etkileyen kodlar yazacaksanız ya da nesnesi olmayan bir class yaratmak istiyorsanız @classmethod kullanmalısınız.
@staticmethodBu metot türünün varlığını sorgulayabilir, "neden var ki?" diyebilirsiniz. Üzerinde çok duramayacağım çünkü aklıma örnek gelmiyor ama dediğim gibi; konular ilerledikçe önemini kavrayacaksınızdır.
Bu metot türü yine aynı şekilde tanımlanır ama içerisine ne self ne de cls argümanını alır. İçerisine herhangi bir argüman almasına gerek yok yani içerisine argüman vermek gibi bir zorunluluk yok ama isterseniz verebilirsiniz.
Ayrıca bu metotlar @classmethod gibi, her hâlükârda çalışacaktır.

Gördüğünüz üzere sadece @staticmethod dedik ve bir metot tanımladık. Ayrıca herhangi bir argüman da vermedik ve kodumuz oldukça güzel çalışıyor.
Bu metot türü, hem class değişkenlerine hem de instance değişkenlerine erişebiliyor. Hemen bakalım.

Gördüğünüz üzere hem class değişkenlerine hem de instance değişkenlerine erişip bazı değerleri ekrana verdim.
Ancak @staticmethod ile tanımladığınız metotlarla class değişkenlerine erişmeniz pek de uygun değildir. Bunu, @classmethod ile yapmak daha uygun olacaktır. Genel olarak normal bir şekilde tanımladığımız ve self argümanını alan metotlar nesne özelliklerine, @classmethod olarak tanımladığımız ve cls argümanını alan metotlar ise class değişkenlerine hitap ediyordu. @staticmethod ile tanımlanan ve argüman alma zorunluluğu olmayan metotları kullanırken ise class değişkenlerine ya da instance yapılarına erişmeye çalışmak yerine özel işlemler yapabiliriz. Bu, daha uygun bir kullanım olacaktır. Örneğin;

tellMe isimli statik metodun görevi 2 ile 4 rakamlarının toplamını döndürmek. Bir başka örnek daha yapalım.

Argüman alma zorunluluğu yok ama istersek verebiliyorduk. Gördüğünüz üzere 3 argüman verdik ve return ifadesiyle birlikte bir matematiksel işlem yaptık. Fonksiyonu çağırırken bu argümanlara değerlerini verdik ve sonucumuz başarıyla geldi.
Bunu şu şekilde de yapabilirdiniz;

Son bir örnek daha yapalım ve bitirelim.

Yukarıdaki örnekte bilmediğiniz bir şey yok. Ancak kısaca özet geçeyim.
*args argümanı sınırsız bir şekilde girdi vermemizi sağlıyordu. Dolayısıyla metodu çağırırken bir sürü sayı girdim; istediğim kadar girebilirim. Metodun içine baktığınızda result = 0 şeklinde bir yapı görüyorsunuz. Bu, verilen *args değerlerinin toplamını tutacak; şu an değeri 0. Sonrasında basit bir for döngüsüyle girdi olarak verilecek olan *args değerlerini sırayla kontrol altına aldım. Hemen sonrasında result += number diyerek verilen her girdiyi topladım ve bu sonucu result değişkenine verdim. Son olarak return result diyerek sonucu ekrana verdim. Metodu çağırırken verdiğim argümanların toplamının doğru bir şekilde çıktı olarak getirildiğini görüyoruz.
Bir sonraki bölümde görüşmek dileğiyle.
Yayınlanma Tarihi: 2022-12-23 16:31:29
Son Düzenleme Tarihi: 2022-12-27 10:49:56