Menu
Coddy logo textTech

Sınıf Dekoratörleri

Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası. Ders 40 / 64.

class decorator'ları, class'ları başka bir function ile sararak onları Modify veya Enhance etmenize olanak tanır. Bunlar function decorator'ları gibi çalışır, ancak tüm class'lara uygulanır.

İşte dekoratör kullanılmamış basit bir class:

class Person:
    def __init__(self, name):
        self.name = name
        
    def greet(self):
        return f"Hello, my name is {self.name}"

Yeni bir method ekleyen bir 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 cls

@ kullanarak decorator'ı bir class'a uygulayın:

@add_farewell
class EnhancedPerson:
    def __init__(self, name):
        self.name = name
        
    def greet(self):
        return f"Hello, my name is {self.name}"

Şimdi class'ın both original ve added methods'i var:

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

Ayrıca mevcut bir method'u sarabilirsiniz: orijinal olanı saklayarak onu sarmalayıcı içinde yine çağırabilirsiniz. Bu, class'ın zaten sahip olduğu bir method'un etrafına behaviour (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 method'u sarmalamak için temel adımlar şunlardır:
1. original method'u kaydedin: original = cls.method
2. original(self)'i ve ek mantığı çağıran yeni bir işlev tanımlayın.
3. Yeni işlevi sınıfa geri atayın: cls.method = new_function
4. modified sınıfı döndürün.

Önemli Nokta: Sınıf dekoratörleri, bir sınıfı input olarak alır, onu değiştirir veya geliştirir ve modified class'ı döndürür. methods ekleyebilir, öznitelikleri değiştirebilir veya mevcut functionality'yi sarmalayabilirler. Bunları uygulamak için class definition'ın üstüne @decorator_name yazın. Bu, kalıtım kullanmadan class functionality'sini 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 decorator'ı uygulayacaksın.

  • decorator.py - add_counter sınıf decorator'ını uygula
  • calculator.py - decorator'ını kullanacak sınıfları içerir

driver.py dosyası, uygulamanı çeşitli kullanım durumlarına, kalıtım düzenlerine 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.

Object Oriented Programming bölümündeki tüm dersler

Kendi başına pratik yap: Online Python derleyicisi