Fonksiyonları Geliştirmek İçin Python Dekoratörleri Nasıl Kullanılır

Python dekoratörleri, işlevleri ve yöntemleri değiştirmek veya geliştirmek için güçlü ve esnek bir yoldur. Dekoratörler, bir işlevi ek işlevsellikle sarmanın bir yolunu sunarak, gerçek kodunu değiştirmeden davranışını genişletmenize olanak tanır. Bu makale sizi dekoratörler kavramıyla, bunların nasıl oluşturulup kullanılacağıyla tanıştıracak ve bazı pratik örnekleri inceleyecektir.

Dekoratör Nedir?

Dekoratör, başka bir işlevi alıp davranışını açıkça değiştirmeden genişleten bir işlevdir. Python'da dekoratörler genellikle mevcut işlevlere veya yöntemlere günlük kaydı, erişim denetimi veya performans ölçümü gibi işlevler eklemek için kullanılır. Dekoratörler, @decorator_name sözdizimini kullanarak işlevlere uygulanır.

# Basic example of a decorator
def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

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

Bir fonksiyona dekoratör uyguladığınızda, Python esasen şu adımları gerçekleştirir:

  1. Dekoratör fonksiyonu, argümanı olarak orijinal fonksiyonla çağrılır.
  2. Dekoratör fonksiyonu, orijinal fonksiyonun davranışını geliştiren veya değiştiren yeni bir fonksiyon tanımlar (genellikle wrapper olarak adlandırılır).
  3. Dekoratör fonksiyonu yeni fonksiyonu döndürür.
  4. Dekore edilmiş fonksiyon çağrıldığında aslında dekoratör tarafından döndürülen yeni fonksiyonu çağırır.

Basit Bir Dekoratör Oluşturma

Bir fonksiyonun yürütme süresini ölçen basit bir dekoratör oluşturalım. Bu, performans testi ve optimizasyonu için faydalıdır.

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Execution time: {end_time - start_time} seconds")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    print("Function finished!")

slow_function()

Argümanlarla Dekoratörleri Kullanma

Bazen, dekoratörünüze argümanlar geçirmek isteyebilirsiniz. Bunu başarmak için bir dekoratör fabrikası oluşturmanız gerekir; bir dekoratör döndüren bir fonksiyon. İşte özel bir mesajı belirtmek için argüman alan bir dekoratörün örneği.

def custom_message_decorator(message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(message)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@custom_message_decorator("Starting the function...")
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Sınıflardaki Yöntemler için Dekoratörler

Dekoratörler, sınıfların içindeki yöntemlerle de kullanılabilir. Yaygın kullanımlar arasında yöntem çağrılarını günlüğe kaydetme, erişim denetimi ve sonuçları önbelleğe alma yer alır. İşte bir sınıftaki yöntem çağrılarını günlüğe kaydetmek için bir dekoratör kullanmanın bir örneği.

def log_method_call(method):
    def wrapper(self, *args, **kwargs):
        print(f"Calling {method.__name__} with arguments {args} and keyword arguments {kwargs}")
        return method(self, *args, **kwargs)
    return wrapper

class MyClass:
    @log_method_call
    def my_method(self, x, y):
        print(f"Result: {x + y}")

obj = MyClass()
obj.my_method(5, 7)

Zincirleme Dekoratörler

Tek bir fonksiyona birden fazla dekoratör uygulayabilirsiniz. Bunlar en içteki dekoratörden en dıştakine doğru uygulanır. Bu, farklı işlevleri bir araya getirmenize olanak tanır. İşte iki dekoratörü zincirlemenin bir örneği:

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def exclamation_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"
    return wrapper

@exclamation_decorator
@uppercase_decorator
def greet(name):
    return f"Hello, {name}"

print(greet("Alice"))

Çözüm

Dekoratörler, Python'da işlevlerin ve yöntemlerin davranışlarını geliştirmenize veya değiştirmenize olanak tanıyan çok yönlü bir araçtır. Dekoratörleri kullanarak, işlevlerinizin temel mantığını değiştirmeden kod tabanınıza yeniden kullanılabilir işlevsellik ekleyebilirsiniz. İster günlük kaydı, ister zamanlama, ister çıktıyı değiştirme olsun, dekoratörler kodunuzun temiz ve sürdürülebilir kalmasına yardımcı olur. Dekoratörleri kullanma pratiği yaparak daha yetkin hale gelin ve Python projelerinizde güçlerinden yararlanın.