Menu
Coddy logo textTech

Sınıf Dekoratörleri

Coddy'nin Python Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 40 / 64.

Sınıf dekoratörleri, sınıfları başka bir işlevle sarmalayarak değiştirmenize veya geliştirmenize olanak tanır. İşlev dekoratörleri gibi çalışırlar, ancak sınıfların tamamına uygulanırlar.

İşte dekorasyon 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 yöntem ekleyen bir sınıf dekoratörü oluşturun:

def add_farewell(cls):
    def farewell(self):
        return f"Goodbye from {self.name}"
    
    cls.farewell = farewell  # Metodu sınıfa ekle
    return cls

Dekoratörü @ kullanarak bir sınıfa 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 özgün hem de eklenen yöntemlere sahip:

person = EnhancedPerson("Alice")
print(person.greet())     # Merhaba, benim adım Alice
print(person.farewell())  # Alice'den hoşça kal

Ayrıca mevcut bir yöntemi sarmalayabilirsiniz: özgün yöntemi saklayarak sarmalayıcının içinde onu yine çağırabilirsiniz. Bu, sınıfın zaten sahip olduğu bir yöntemin 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")   # Önce 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 çağrıldığında, önce sarmalayıcı çalışır, ardından özgün işlevi çağırır:

person = TrackedPerson("Alice")
print(person.greet())
# greet çağrıldı
# Merhaba, benim adım Alice

Mevcut bir yöntemi sarmalamak için temel adımlar şunlardır:
1. Özgün yöntemi kaydedin: original = cls.method
2. original(self) çağrısını ve ek mantığı içeren yeni bir işlev tanımlayın.
3. Yeni işlevi sınıfa geri atayın: cls.method = new_function
4. Değiştirilmiş sınıfı döndürün.

Temel 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 sarabilirler. Bunları uygulamak için sınıf tanımının üstüne @decorator_name ekleyin. Bu, kalıtım kullanmadan sınıf işlevselliğini genişletmek için temiz bir yol sağlar.

challenge icon

Görev

Orta

Bu görevde, yöntem çağrılarını izleme işlevselliği ekleyen bir sınıf dekoratörü uygulayacaksın.

  • decorator.py - add_counter sınıf dekoratörünü uygula
  • calculator.py - Dekoratörünü kullanacak sınıfları içerir

driver.py dosyası, uygulamanı çeşitli kullanım durumları, kalıtım biçimleri ve uç durumlara karşı doğrulayacak kapsamlı test senaryoları içerir. Bu dosyada değişiklik yapmana gerek yok, ancak dosyayı incelemek beklenen davranışı anlamana yardımcı olacaktır.

Kendin dene

from calculator import Calculator

# Kapsamlı test durumu 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)  # Should print {'add': 2, 'subtract': 1}

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'u paylaşmalı
    print(calc1.call_counts)  # Should print {'add': 2, 'subtract': 1}
    print(calc2.call_counts)  # Should print {'add': 2, 'subtract': 1}
    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)  # Should print {'add': 3, 'subtract': 1}

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)  # Should print {'add': 1, 'subtract': 1}

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)  # Should print {'add': 1, 'subtract': 1}

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)  # Should print {'add': 1, 'subtract': 1}

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)  # Should print {'add': 1, 'subtract': 1}

elif test_case == "counter_reset":
    calc = Calculator()
    
    print(calc.add(5, 3))  # 8 yazdırmalı
    print(calc.call_counts)  # Should print {'add': 1, 'subtract': 0}
    
    # Sayacı sıfırla
    calc.call_counts = {"add": 0, "subtract": 0}
    
    print(calc.add(2, 7))  # 9 yazdırmalı
    print(calc.call_counts)  # Should print {'add': 0, 'subtract': 0}

elif test_case == "counter_manipulation":
    calc = Calculator()
    
    print(calc.add(5, 3))  # 8 yazdırmalı
    print(calc.call_counts)  # Should print {'add': 1, 'subtract': 0}
    
    # Sayacı doğrudan manipüle et
    calc.call_counts["add"] = 100
    
    print(calc.add(2, 7))  # 9 yazdırmalı
    print(calc.call_counts)  # Should print {'add': 101, 'subtract': 0}

elif test_case == "performance_test":
    calc = Calculator()
    
    # 1000 add işlemi gerçekleştir
    for i in range(1000):
        calc.add(i, i+1)
    
    # 500 subtract işlemi gerçekleştir
    for i in range(500):
        calc.subtract(i+10, i)
    
    print(calc.call_counts)  # Should print {'add': 1000, 'subtract': 500}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Python derleyicisi