Python, sınıf tanımlarında üç tür yöntem destekler: örnek yöntemler, sınıf yöntemleri ve statik yöntemler. Bu yöntemler, çağrılma şekli ve sınıf ile örnek verilerine erişim açısından farklılık gösterir.
Tarihçe:
Başlangıçta sınıf yöntemleri ("self" ile olanlar) tek tür davranıştı ve yöntemlerin her zaman belirli bir nesnenin verilerini değiştirmesi veya okuması bekleniyordu. Daha sonra Python'da sınıf davranışı sağlayan sınıf yöntemleri ("cls" ile) ve sınıfa bağlı ancak normal işlevlere benzer statik yöntemler ortaya çıktı.
Sorun:
Bazen tüm örnekler için genel bir işlevsellik gerekir (statik yöntemler). Bazen de - işlemin "tüm sınıfa" ait olması gerekir (örneğin, bir örnek oluşturma). Ancak, yanlış yöntem türünü tanımlamak, hatalara neden olabilir (örneğin, bir nesne yöntemi üzerinden sınıfı değiştirmeye çalışmak ya da tersine).
Çözüm:
Kod örneği:
class MyClass: def instance_method(self): return f"Örnek: {self}" @classmethod def class_method(cls): return f"Sınıf: {cls}" @staticmethod def static_method(): return "Bu bir statik yöntem" obj = MyClass() print(obj.instance_method()) # Örnek: <MyClass object...> print(MyClass.class_method()) # Sınıf: <class 'MyClass'> print(MyClass.static_method()) # Bu bir statik yöntem
Ana özellikler:
Bir örnek yöntemi doğrudan sınıf üzerinden çağırmak mümkün mü?
Mümkündür, ancak nesneyi açıkça iletmek gerekmektedir:
MyClass.instance_method(obj)
bu nadiren uygun olur.
Statik yöntemlerin kalıtımda davranışı: yeniden tanımlanabilirler mi?
Evet, aynı adı taşıyan bir staticmethod'u alt sınıfta tanımlayabilir ve miras alan nesne üzerinden çağrıldığında bu tanım kullanılacaktır.
Eğer her zaman cls parametresi ile statik yöntemler kullanılabiliyorsa, sınıf yöntemleri neden kullanılmaktadır?
cls sadece ilk argüman değildir: classmethod'da Python, çağrının alt sınıftan yapılması bile olsa, uygun olan sınıfı cls olarak otomatik olarak atar. Bu, ana sınıfa sıkı bir bağlılık olmadan alternatif yapıcı hiyerarşileri oluşturmayı sağlar.
Örnek:
class Base: @classmethod def make(cls): return cls() class Child(Base): pass Child.make() # Child döndürür, Base değil
Projede alternatif örnekler oluşturmak için normal yöntemler kullanıldı (örneğin, create_from_json). Bu nedenle alt sınıfta kalıtımda, yöntem her zaman temel sınıfın nesnesini döndürüyor, miras alan nesneyi değildi.
Artılar:
Eksiler:
Şu anki sınıfın örneklerini döndüren classmethod fabrikaları uygulandı (cls()), hatta alt sınıftan çağrıldıklarında bile.
Artılar:
Eksiler: