Sınıf Dekoratörleri
Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 40 / 64.
Sınıf dekoratörleri, sınıfları başka bir fonksiyonla sarmalayarak değiştirmenize veya geliştirmenize olanak tanır. Fonksiyon dekoratörleri gibi çalışırlar ancak tüm sınıflara uygulanırlar.
İşte dekoratör içermeyen basit bir sınıf:
class Person:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Yeni bir metot ekleyen bir sınıf dekoratörü (class decorator) oluşturun:
def add_farewell(cls):
def farewell(self):
return f"Goodbye from {self.name}"
cls.farewell = farewell # Metodu sınıfa ekle
return clsDekoratörü bir sınıfa @ kullanarak uygulayın:
@add_farewell
class EnhancedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Artık sınıf hem orijinal hem de eklenen metotlara sahip:
person = EnhancedPerson("Alice")
print(person.greet()) # Merhaba, benim adım Alice
print(person.farewell()) # Alice'den elvedaAyrıca, mevcut bir metodu sarmalayabilirsiniz — orijinalini saklayarak sarmalayıcı içinde hala çağırabilmenizi sağlar. Bu, sınıfın halihazırda sahip olduğu bir metodun etrafına davranış (izleme veya günlük kaydı gibi) eklemek istediğinizde kullanışlıdır:
def add_tracking(cls):
original_greet = cls.greet # Orijinal metodu sakla
def tracked_greet(self):
print(f"greet was called") # Öncesinde ekstra davranış
return original_greet(self) # Orijinal metodu çağır
cls.greet = tracked_greet # Sınıftaki metodu değiştir
return cls
@add_tracking
class TrackedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Şimdi greet fonksiyonunu çağırdığınızda, önce sarmalayıcı çalışır, ardından orijinal fonksiyona devreder:
person = TrackedPerson("Alice")
print(person.greet())
# greet çağrıldı
# Hello, my name is AliceMevcut bir metodu sarmalamak için temel adımlar şunlardır:
1. Orijinal metodu kaydedin: original = cls.method
2. original(self) çağrısını ve ek mantığı içeren yeni bir fonksiyon tanımlayın.
3. Yeni fonksiyonu sınıfa geri atayın: cls.method = new_function
4. Değiştirilmiş sınıfı döndürün.
Önemli Nokta: Sınıf dekoratörleri girdi olarak bir sınıf alır, onu değiştirir veya geliştirir ve değiştirilmiş sınıfı döndürür. Metotlar ekleyebilir, öznitelikleri değiştirebilir veya mevcut işlevselliği sarmalayabilirler. Bunları uygulamak için sınıf tanımının üzerinde @decorator_name kullanın. Bu, kalıtım kullanmadan sınıf işlevselliğini genişletmek için temiz bir yol sağlar.
Görev
OrtaBu meydan okumada, metot çağrısı izleme özelliği ekleyen bir sınıf dekoratörü uygulayacaksınız.
decorator.py-add_countersınıf dekoratörünü uygulayıncalculator.py- Dekoratörünüzü kullanacak sınıfları içerir
driver.py dosyası, uygulamanızı çeşitli kullanım durumlarına, kalıtım modellerine ve uç durumlara karşı doğrulayacak kapsamlı test senaryoları içerir. Bu dosyayı değiştirmenize gerek yoktur, ancak dosyayı incelemek beklenen davranışı anlamanıza yardımcı olacaktır.
Kopya kağıdı
Sınıf dekoratörleri (class decorators), sınıfları başka bir fonksiyonla sarmalayarak onları değiştirir veya geliştirir. Girdi olarak bir sınıf alırlar, onu değiştirirler ve değiştirilmiş sınıfı geri döndürürler.
Temel sınıf dekoratörü sözdizimi:
def decorator_name(cls):
# Modify the class
return cls
@decorator_name
class MyClass:
passÖrnek - bir sınıfa metot ekleme:
def add_farewell(cls):
def farewell(self):
return f"Goodbye from {self.name}"
cls.farewell = farewell # Add the method to the class
return cls
@add_farewell
class EnhancedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"
person = EnhancedPerson("Alice")
print(person.greet()) # Hello, my name is Alice
print(person.farewell()) # Goodbye from AliceÖrnek - mevcut bir metodu sarmalama (orijinali sakla, sonra değiştir):
def loud_greet(cls):
original_greet = cls.greet # Store the original method
def new_greet(self):
result = original_greet(self) # Call the original
return result.upper() # Enhance the result
cls.greet = new_greet # Replace with the wrapped version
return cls
@loud_greet
class EnhancedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"
person = EnhancedPerson("Alice")
print(person.greet()) # HELLO, MY NAME IS ALICEMevcut bir metodu sarmalamak için temel adımlar:
original = cls.method_name — orijinal metodu kaydetdef new_method(self): original(self) — sarmalayıcı içinde onu çağırcls.method_name = new_method — sınıftaki metodu yenisiyle değiştirSınıf dekoratörleri, kalıtım (inheritance) kullanmadan metot ekleyebilir, öznitelikleri değiştirebilir veya mevcut işlevselliği sarmalayabilir.
Kendin dene
from calculator import Calculator
# Kapsamlı test senaryosu işleyicisi
test_case = input()
if test_case == "basic_functionality":
calc = Calculator()
print(calc.add(5, 3)) # 8 yazdırmalı
print(calc.add(2, 7)) # 9 yazdırmalı
print(calc.subtract(10, 4)) # 6 yazdırmalı
print(calc.call_counts) # {'add': 2, 'subtract': 1} yazdırmalı
elif test_case == "multiple_instances":
calc1 = Calculator()
calc2 = Calculator()
print(calc1.add(5, 3)) # 8 yazdırmalı
print(calc2.add(2, 7)) # 9 yazdırmalı
print(calc1.subtract(10, 4)) # 6 yazdırmalı
# Her iki örnek de aynı call_counts değerini paylaşmalı
print(calc1.call_counts) # {'add': 2, 'subtract': 1} yazdırmalı
print(calc2.call_counts) # {'add': 2, 'subtract': 1} yazdırmalı
print(calc1.call_counts is calc2.call_counts) # True yazdırmalı
elif test_case == "method_call_order":
calc = Calculator()
print(calc.add(1, 2)) # 3 yazdırmalı
print(calc.subtract(5, 2)) # 3 yazdırmalı
print(calc.add(10, 20)) # 30 yazdırmalı
print(calc.add(7, 3)) # 10 yazdırmalı
print(calc.call_counts) # {'add': 3, 'subtract': 1} yazdırmalı
elif test_case == "large_values":
calc = Calculator()
print(calc.add(1000000, 2000000)) # 3000000 yazdırmalı
print(calc.subtract(5000000, 2000000)) # 3000000 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 1} yazdırmalı
elif test_case == "negative_values":
calc = Calculator()
print(calc.add(-5, -3)) # -8 yazdırmalı
print(calc.subtract(-10, -4)) # -6 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 1} yazdırmalı
elif test_case == "float_values":
calc = Calculator()
print(calc.add(5.5, 3.2)) # 8.7 yazdırmalı
print(calc.subtract(10.5, 4.2)) # 6.3 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 1} yazdırmalı
elif test_case == "zero_values":
calc = Calculator()
print(calc.add(0, 0)) # 0 yazdırmalı
print(calc.subtract(0, 0)) # 0 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 1} yazdırmalı
elif test_case == "counter_reset":
calc = Calculator()
print(calc.add(5, 3)) # 8 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 0} yazdırmalı
# Sayacı sıfırla
calc.call_counts = {"add": 0, "subtract": 0}
print(calc.add(2, 7)) # 9 yazdırmalı
print(calc.call_counts) # {'add': 0, 'subtract': 0} yazdırmalı
elif test_case == "counter_manipulation":
calc = Calculator()
print(calc.add(5, 3)) # 8 yazdırmalı
print(calc.call_counts) # {'add': 1, 'subtract': 0} yazdırmalı
# Sayacı doğrudan manipüle et
calc.call_counts["add"] = 100
print(calc.add(2, 7)) # 9 yazdırmalı
print(calc.call_counts) # {'add': 101, 'subtract': 0} yazdırmalı
elif test_case == "performance_test":
calc = Calculator()
# 1000 toplama işlemi gerçekleştir
for i in range(1000):
calc.add(i, i+1)
# 500 çıkarma işlemi gerçekleştir
for i in range(500):
calc.subtract(i+10, i)
print(calc.call_counts) # {'add': 1000, 'subtract': 500} yazdırmalıBu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerself ParametresiMetotlarÖzniteliklerYapıcı Metot (__init__)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımsuper() FonksiyonuMetot Geçersiz KılmaÇoklu KalıtımMetot Çözümleme SırasıÖzet - Çalışan Hiyerarşisi7Özel Metotlar
Sihirli Metotlara GirişOperatör Aşırı YüklemeKapsayıcı Sihirli MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım kalıplarına girişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı13Final Meydan Okumaları
E-öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi5Çok Biçimlilik (Polymorphism)
Metot Geçersiz Kılmaya Yeniden BakışDuck TypingSoyut Sınıflar ve MetotlarArayüz TasarımıÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon ve KalıtımMixinsStatik ve Sınıf MetotlarıSınıf DekoratörleriBağlam Yöneticileri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit Kalıbı