2.23. Dekoratörler#
Dekoratör, bir fonksiyonu (veya bir yöntemi) başka bir fonksiyonla saran bir söz dizimi parçasıdır. Sarmalayıcı, orijinal çağrıdan önce ve sonra davranış ekleyebilir, dönüş değerini değiştirebilir veya meta veri ekleyebilir. Biçimi şöyledir:
@wrapper
def f():
...
@wrapper satırı f = wrapper(f) ifadesine eşdeğerdir – f fonksiyonu normal şekilde oluşturulur, ardından wrapper‘a verilir ve sonuç f adına yeniden bağlanır.
Bir dekoratör bir fonksiyon alır ve yeni bir fonksiyon döndürür.#
2.23.1. Yerleşik yöntem dekoratörleri#
Python ile birlikte gelen ve sınıf gövdeleri içinde kullanılan birkaç dekoratör vardır.
2.23.1.1. @property#
Bir yöntemi hesaplanmış bir niteliğe dönüştürür. Çağıran, sanki düz bir nitelikmiş gibi ona erişir (parantez yok), ancak her okumada bir yöntem çalışır:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return 3.14159 * self.radius * self.radius
c = Circle(5)
print(c.area) # 78.53975 -- no parentheses
Bunu, basit görünen bir niteliğin arkasında küçük bir hesaplama gerektiğinde kullanın. İş pahalıysa, normal bir yöntemi tercih edin – çağıranlar nitelik okumalarının yavaş olmasını beklemez.
2.23.1.2. @classmethod#
Bir örnek yerine ilk argümanı olarak sınıfı alan bir yöntem tanımlar. İlk parametre geleneksel olarak cls olarak adlandırılır:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def origin(cls):
return cls(0, 0)
p = Point.origin()
Sınıf yöntemleri, alternatif kurucular sağlamanın standart yoludur – varsayılan olmayan bir şekilde oluşturulmuş bir örnek döndüren fabrika fonksiyonları.
2.23.1.3. @staticmethod#
Ne örneği ne de sınıfı alan bir yöntem tanımlar – bu, yalnızca düzenleme nedenleriyle sınıf ad alanında yaşayan düz bir fonksiyondur:
class Temperature:
@staticmethod
def c_to_f(c):
return c * 9 / 5 + 32
Temperature.c_to_f(100) # 212.0
Bunu idareli kullanın; bir fonksiyonun gerçekten sınıfın durumuyla hiçbir ilgisi yoksa, düz bir modül düzeyinde fonksiyon genellikle daha temizdir.
2.23.2. Özel bir dekoratör yazmak#
Dekoratör, bir fonksiyon alıp bir fonksiyon döndüren bir fonksiyondur. Minimum biçim:
def log_calls(func):
def wrapper(*args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
return wrapper
@log_calls
def add(a, b):
return a + b
add(2, 3)
Çıktı:
calling add
wrapper, func üzerinde kapanış oluşturur ve her şeyi ona iletir. *args / **kwargs, yalnızca iki argümanlı olanlar için değil, herhangi bir fonksiyon üzerinde çalışmasını sağlar. Bu kalıp, daha ayrıntılı dekoratörlerin (zamanlama, önbellekleme, başarısızlıkta yeniden deneme) temelidir ancak özü her zaman aynıdır: bir fonksiyon al, bir fonksiyon döndür.