Python'da Dekoratörler

Python'da Dekoratörler

Bu makale, Python'daki dekoratörleri açıklar.

YouTube Video

Python'da Dekoratörler

Python'daki dekoratörler, fonksiyonlara veya metodlara ek işlevsellik eklemek için kullanılan güçlü bir özelliktir. Dekoratörler, mevcut kodu değiştirmeden yeni işlevsellik eklemenize olanak tanır, böylece kod yeniden kullanılabilirliği ve bakım kolaylığı artar.

Dekoratörlerin Temelleri

Python dekoratörleri, bir fonksiyonu argüman olarak alır ve eklenen işlevsellikle yeni bir fonksiyon döndürür. Dekoratörleri kullanarak fonksiyonlara kolayca ön işleme veya son işleme ekleyebilirsiniz.

Dekoratörler olmadan, bir fonksiyonun davranışını değiştirmek, doğrudan fonksiyonu düzenlemeyi gerektirir. Dekoratörlerle, orijinal uygulamayı değiştirmeden işlevselliği genişletebilirsiniz.

Bir Dekoratörün Temel Yapısı

 1def my_decorator(func):
 2    def wrapper():
 3        print("Before the function call")
 4        func()
 5        print("After the function call")
 6    return wrapper
 7
 8@my_decorator
 9def say_hello():
10    print("Hello!")
11
12say_hello()

Bu örnekte, my_decorator fonksiyonu bir dekoratör olarak hizmet eder ve say_hello fonksiyonunu sarar. Dekoratör, @my_decorator sözdizimi kullanılarak uygulanır ve say_hello() çağrıldığında, dekoratör tarafından sağlanan ön işleme ve son işleme otomatik olarak gerçekleştirilir.

Dekoratörler Nasıl Çalışır

Dekoratörler aşağıdaki adımlarla çalışır.

  1. Dekoratör, bir fonksiyonu (veya metodu) argüman olarak alır.

  2. Orijinal fonksiyonu çalıştırmak için bir sarmalayıcı fonksiyon tanımlar.

  3. Sarmalayıcı fonksiyon, orijinal fonksiyonu çalıştırmadan önce veya sonra ek işlem yapar.

  4. Dekoratör, sarmalayıcı fonksiyonu döndürür. Sonuç olarak, orijinal fonksiyon yeni, dekore edilmiş bir fonksiyonla değiştirilir.

Argüman Alan Fonksiyonlar için Dekoratörler

Bir dekoratörü argüman alan bir fonksiyona uygularken, sarmalayıcı fonksiyonun bu argümanları kabul edecek şekilde ayarlanması gerekir.

 1def my_decorator(func):
 2    def wrapper(*args, **kwargs):
 3        print("Before the function call")
 4        result = func(*args, **kwargs)
 5        print("After the function call")
 6        return result
 7    return wrapper
 8
 9@my_decorator
10def greet(name):
11    print(f"Hello, {name}!")
12
13greet("Alice")

*args ve **kwargs kullanarak, herhangi bir sayıda argüman ve anahtar kelime argümanını kabul eden fonksiyonları işlemek mümkündür. Bu, dekoratörlerin herhangi bir türdeki argümanlarla fonksiyonlara genel olarak uygulanmasını sağlar.

Dekoratörlerin Uygulanmasına Örnekler

Kayıt Tutma İçin Dekoratör

Dekoratörler genellikle kayıt tutma işlevselliği eklemek için kullanılır. Örneğin, bir fonksiyonun yürütülmesinden önce ve sonra kayıt tutan bir dekoratör oluşturarak, fonksiyonun ne zaman çağrıldığını ve ne kadar sürdüğünü kaydedebilirsiniz.

 1import time
 2
 3def log_time(func):
 4    def wrapper(*args, **kwargs):
 5        start_time = time.time()
 6        print(f"Calling function '{func.__name__}'...")
 7        result = func(*args, **kwargs)
 8        end_time = time.time()
 9        print(f"Function '{func.__name__}' completed in {end_time - start_time} seconds")
10        return result
11    return wrapper
12
13@log_time
14def long_task(duration):
15    time.sleep(duration)
16    print("Task completed!")
17
18long_task(2)

Bu örnekte, log_time dekoratörü bir fonksiyonun çalışma süresini ölçer ve bunu bir kayıt olarak çıktılar. long_task fonksiyonu dekoratör ile sarılmıştır ve çalışma süresi yürütme sırasında kaydedilir.

İzin Yönetimi İçin Dekoratör

Dekoratörler ayrıca izin yönetimi için de kullanılabilir. Örneğin, bir kullanıcının belirli izinlere sahip olup olmadığını kontrol ederek işlemleri kısıtlayabilirsiniz.

 1def requires_permission(user_role):
 2    def decorator(func):
 3        def wrapper(*args, **kwargs):
 4            if user_role != "admin":
 5                print("Permission denied!")
 6                return
 7            return func(*args, **kwargs)
 8        return wrapper
 9    return decorator
10
11@requires_permission("admin")
12def delete_user(user_id):
13    print(f"User {user_id} has been deleted.")
14
15delete_user(123)  # Executed
16delete_user = requires_permission("guest")(delete_user)
17delete_user(456)  # Permission denied!

requires_permission dekoratörü, bir kullanıcının rolüne bağlı olarak bir fonksiyonun çalıştırılmasını kısıtlar. Bu tür bir mantığı bir dekoratör içinde birleştirerek, izin yönetimi mantığının kodunuzun her yerine yayılmasını önleyebilir ve okunabilirliği artırabilirsiniz.

Dekoratörlerin Birleştirilmesi

Birden fazla dekoratör uygulamak mümkündür. Bir fonksiyona birden fazla dekoratör uygulandığında, bunlar yukarıdan aşağıya doğru sırayla çalıştırılır.

 1def uppercase(func):
 2    def wrapper(*args, **kwargs):
 3        result = func(*args, **kwargs)
 4        return result.upper()
 5    return wrapper
 6
 7def exclaim(func):
 8    def wrapper(*args, **kwargs):
 9        result = func(*args, **kwargs)
10        return result + "!"
11    return wrapper
12
13@uppercase
14@exclaim
15def greet(name):
16    return f"Hello, {name}"
17
18print(greet("Alice"))  # "HELLO, ALICE!"

Bu örnekte, greet fonksiyonuna iki dekoratör uygulanmıştır. @exclaim dekoratörü dizenin sonuna bir ünlem işareti ekler, ardından @uppercase diziyi büyük harflere çevirir.

Sınıf Yöntemleri İçin Dekoratörler

Dekoratörler ayrıca sınıf yöntemleri ile de kullanılabilir. Bu, özellikle bir sınıftaki yöntemlerin davranışını kontrol etmek istediğinizde faydalıdır. Sınıf yöntemlerine dekoratör uygularken self veya cls gibi argümanlara dikkat etmeniz gerekir.

 1def log_method_call(func):
 2    def wrapper(self, *args, **kwargs):
 3        print(f"Calling method '{func.__name__}'...")
 4        return func(self, *args, **kwargs)
 5    return wrapper
 6
 7class MyClass:
 8    @log_method_call
 9    def greet(self, name):
10        print(f"Hello, {name}")
11
12obj = MyClass()
13obj.greet("Bob")

Bu örnekte, log_method_call dekoratörü greet yöntemine uygulanmıştır ve yöntem çağrıldığında bir kayıt çıktılar.

Dekoratörler İle İlgili Dikkat Edilecekler

Dekoratör kullanırken dikkate alınması gereken bazı hususlar vardır. Dekoratörler, orijinal fonksiyonun adını ve dokümantasyon metnini (örneğin, __name__ veya __doc__) değiştirebilir, bu nedenle bu bilgiyi korumak için functools.wraps kullanılması önerilir.

1import functools
2
3def my_decorator(func):
4    @functools.wraps(func)
5    def wrapper(*args, **kwargs):
6        print("Before the function call")
7        return func(*args, **kwargs)
8    return wrapper

@functools.wraps kullanımı, orijinal fonksiyonun meta verilerinin doğru bir şekilde sarmalayıcı fonksiyona aktarılmasını sağlar.

Özet

Python dekoratörleri, işlevlere ve metodlara ek işlevselliği özlü bir şekilde eklemenize olanak tanıyan çok güçlü bir araçtır. Kod tekrarlanmasını azaltmak, bakım kolaylığını ve yeniden kullanılabilirliği artırmak için farklı senaryolarda kullanılabilirler. Dekoratörlerin nasıl çalıştığını anlayarak daha verimli ve esnek kodlar yazabilirsiniz.

Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.

YouTube Video