Soru Tarihi:
Python'da her şey bir nesnedir ve her işlev de bir nesnedir. Bir sınıf örneğinin işlev gibi çalışmasını sağlayan bir mekanizma gerçekleştirilmiştir. Bunun için, nesneleri çağrılabilir hale getiren özel bir sihirli metod olan call tanıtılmıştır.
Sorun:
Bazen, çağrılabilen bir nesneyi geçmek gerekebilir; örneğin, durumlu fonksiyonlar, kapanışlar, olay işleyici nesneleri vb. Geliştirme mimarisi, bu tür işlevselliğin nasıl doğru bir şekilde uygulanacağını anlamayı gerektirir.
Çözüm:
Bir sınıfta call metodunu uygulayarak, onun örneğini "işlev gibi" çağrılabilir hale getirebiliriz. Bu, sınıfların (durum kapsülleme, miras alma, metodlar) ve işlevlerin (çağrılabilirlik) olanaklarını birleştirmeyi sağlar. Bu yaklaşım, komut nesneleri, karmaşık işleyiciler, sarıcılar vb. oluşturmak için kullanılır.
Kod Örneği:
class Adder: def __init__(self, x): self.x = x def __call__(self, y): return self.x + y add5 = Adder(5) print(add5(10)) # 15'i yazdırır
Ana özellikler:
call metodu, sıradan bir işlevin niteliklerini miras alır mı — örneğin, name ve doc?
Hayır, call metoduna sahip bir nesnenin name niteliği olmayacaktır (veya sınıftan devralır). İşlevlerin meta verileri saklanmaz.
call gerçekleştirilmiş bir nesne gerçek bir işlev midir?
Hayır, bu bir sınıf örneğidir, işlev değildir. Sadece "çağrılabilir" davranışını gerçekleştirir. Örneğin, isinstance(obj, types.FunctionType) ile işlevle karşılaştırmak False verir.
call olan bir nesneye, işlev için tasarlanmış bir dekoratör uygulanabilir mi?
Genellikle bu tür dekoratörler, tam olarak bir işlev bekler, nesne değil (örneğin, functools.lru_cache). Kullanım hatalara yol açabilir veya hiç çalışmayabilir.
Artılar:
Olumsuz durum: Bir projede ayarları (seviye, dosya adı) saklamak için call ile bir günlüğü sınıf olarak gerçekleştirdiler. Ancak, sinyal işleyicilerinin tam olarak bir işlev beklediğini unuttular ve işleyiciyi kaydederken hatalar aldılar (object is not a function).
Artılar: günlüğün esnek ayarları. Eksiler: beklenen arayüzlerle uyumsuzluk.
Olumlu durum: Başka bir projede, parametreleri saklamak için call ile karmaşık dekoratör işlevleri oluşturmak için bir sınıf kullandılar, bu da test etmeyi kolaylaştırdı.
Artılar: genişletilebilirlik, kullanım kolaylığı. Eksiler: işlev veya lambda ile karşılaştırıldığında daha fazla kod.