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.