14.2. Decorators

Bir decorator fonksiyonu alır, bazı fonksiyonellikler ekler ve onu döndürür. Meta programlama olarak bilinen ve derleme sırasında (burada yorumlama) programın parçalarının diğer program parçalarını değiştirmeyi denemesi olarak açıklanabilir. Bu bölüm decorator konusuna ayrılmıştır. Öncelikle bir Python konusunda ayrıntıları hatırlayalım. Python’da her şey bir nesnedir (object). Tanımladığınız isimler bu nesnelere bağlanmak için kullanılır. Fonksiyonlarda birer nesnedir. Hatta aynı fonksiyon çeşitli adlarla tanımlanabilir. Örneğin,

Kodu çalıştırdığınızda hem ilk_func hem de ikinci aynı sonucu döndürür. Hatta, id fonksiyonu ile bellek bölgelerine baktığımızda aynı bellek bölgesini işaret eder. Fonksiyon içinden fonksiyonu değer olarak göndermeyi destekler. Bunlara daha öncelikli fonksiyonlar ismi verilir. Örneğin,

Hatta, bir fonksiyon diğer bir fonksiyonu döndürebilir.

Bir önceki closure konusunu hatırlatan bir örnek oldu.

14.2.1. Decorators

Bu kadar ön bilgiden sonra decorator konusuna başlayalım. Fonksiyon ve metotlar çağrılabilirdir. __call__() özel metodu ile herhangi bir nesneye çağırma işlemi uygulanabilir. Bir decorator’de çağrılabilen bir nesnedir. Temel olarak bir decorator bir fonksiyonu alır, yeni fonksiyonellikler ekler ve döndürür.

Şimdi aynı işlemi @ sembolünü decorator fonksiyonunu kullanmak istediğimiz fonksiyon üzerinde kullanalım.

Aslında bu işlemin aşağıdaki satırlardan hiç bir farkı yoktur. Ancak @ kullanmak kodun okunurluğunu arttırır.

 nesne = decorator_ornek

(fonksiyon) nesne()

14.2.2. Parametreler ile Decorators

Öncelikle bir problem yaratalım. Sıfıra bölme hatası problemimiz olsun. Örneğin aşağıdaki gibi bir fonksiyonumuz olsun.

Gelin bir decorator yaparak bu hatalı duruma basit bir çözüm üretelim. Eğer sıfıra bölme yapılırsa, basit bir hata üretsin.

b sıfır olduğunda bir çıktı üretip, boş bir return işlemi gerçekleşir. Bu sayede kod hata oluşturmaz hale gelir. Yukarıdaki kodun çıktısı:

Yukarıdaki örnekte iki argüman gönderildi. Eğer birden fazla argüman göndermek istiyorsak, “*args and **kwargs” kullanılabilir. args bir tuple verisi alırken kwargs ise bir dictionary verisi alır. Bu durumda tüm fonksiyonlarda kullanılabilecek kod:

14.2.3. Decorators Zincirleme (Chaining)

Birden fazla decorator aynı kullanılabilir. Ancak kullanım sırası sonucu etkileyebilir. Basit bir örnekle açıklayalım.

Bu örnekte fonksiyondan dönen değerin çevresine yıldız ve yüzde karakterleri ekleniyor. Decorator fonksiyonlar 30 adet yıldız ve yüzde oluşturuyor. Örnekte öncelikle yildiz sonrasında yuzde decorator’u aktive ediliyor. Sıralamayı değiştirirsek: