Menu
CoddyTech

İleri Seviye Property Dekoratörleri

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

Gelişmiş özellik dekoratörleri, hesaplanan özellikler, silme yöntemleri ve kapsamlı özellik yönetimi de dahil olmak üzere öznitelik erişimi üzerinde daha gelişmiş bir kontrol sağlar.

İşte diğer özniteliklerden değer türeten hesaplanmış özelliklere bir örnek:

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    @property
    def area(self):
        return self.width * self.height
    
    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

Hesaplanan özellikleri normal öznitelikler gibi kullanın:

rect = Rectangle(5, 3)
print(rect.area)      # 15 - otomatik olarak hesaplanır
print(rect.perimeter) # 16 - otomatik olarak hesaplanır

Getter, setter ve deleter içeren bir özellik oluşturun:

class Temperature:
    def __init__(self):
        self._temp = 0
    
    @property
    def temperature(self):
        return self._temp
    
    @temperature.setter
    def temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below absolute zero!")
        self._temp = value
    
    @temperature.deleter
    def temperature(self):
        print("Resetting temperature to 0")
        self._temp = 0

Özelliğin tüm işlevselliğini kullan:

temp = Temperature()

Doğrulamayla ayarlayıcıyı kullanın:

temp.temperature = 25
print(temp.temperature)  # 25

# temp.temperature = -300  # ValueError hatası oluşturur

Siliciyi kullan:

del temp.temperature
print(temp.temperature)  # 0

Oyun puanıyla daha karmaşık bir örnek oluşturun:

class Player:
    def __init__(self, name):
        self.name = name
        self._score = 0
        self._level = 1
    
    @property
    def score(self):
        return self._score
    
    @score.setter
    def score(self, value):
        if value >= 0:
            self._score = value
            self._level = (value // 1000) + 1
        else:
            raise ValueError("Score cannot be negative")
    
    @score.deleter
    def score(self):
        print(f"Resetting {self.name}'s progress")
        self._score = 0
        self._level = 1
    
    @property
    def level(self):
        return self._level

player = Player("Alice")
player.score = 2500
print(f"Score: {player.score}, Level: {player.level}")  # Puan: 2500, Seviye: 3

del player.score
print(f"Score: {player.score}, Level: {player.level}")  # Puan: 0, Seviye: 1

Çıktı:

15
16
25
Resetting temperature to 0
0
Score: 2500, Level: 3
Resetting Alice's progress
Score: 0, Level: 1

Önemli Nokta: Gelişmiş özellik dekoratörleri, hesaplanmış özelliklere (diğer verilerden hesaplanan), @property.deleter ile özellik silmeye ve öznitelikleri alma, ayarlama ve silme üzerinde tam denetime olanak tanır. Bu, güçlü veri doğrulama ve kapsüllemeyi korurken sezgisel arayüzler oluşturur.

challenge icon

Görev

Orta

Bu meydan okumada, uygun kapsülleme ve özellik doğrulaması içeren bir Rectangle sınıfı uygulayacaksın.

  • rectangle.py - Bu, uygulamana rehberlik edecek TODO yorumlarını içeren, düzenlemen gereken dosyadır
  • driver.py - Kapsamlı test senaryoları içerir (değiştirme)
  1. _width ve _height için özel öznitelikler uygula
  2. Doğrulama içeren width ve height özellikleri oluştur (pozitif olmalılar)
    • TODO'larda belirtildiği şekilde uygun ValueError mesajlarını yükselt
    • Önemli: Değerin 0'dan küçük veya 0'a eşit olup olmadığını kontrol et, ardından hatayı yükselt (bu, tutarlı davranış sağlar)
  3. area ve perimeter için salt okunur özellikler uygula
  4. TODO'larda açıklandığı şekilde alıcı, ayarlayıcı ve silici işlevleri olan bir dimensions özelliği oluştur
    • Önemli: Ayarlayıcıda, demet açma sözdizimini kullan: width, height = dimensions

Kendin dene

from rectangle import Rectangle

# Test durumu işleyicisi
test_case = input()

# Temel işlevsellik testi
if test_case == "default_test":
    rect = Rectangle(5, 3)
    print(f"Width: {rect.width}, Height: {rect.height}")
    print(f"Area: {rect.area}, Perimeter: {rect.perimeter}")
    
    # dimensions özelliğini test et
    print(f"Dimensions: {rect.dimensions}")
    rect.dimensions = (10, 8)
    print(f"New area: {rect.area}")
    
    # Doğrulamayı test et
    try:
        rect.width = -2
    except ValueError as e:
        print(f"Validation error: {e}")
    
    # Siliciyi test et
    del rect.dimensions
    print(f"After reset: {rect.dimensions}")

# Sıfır değerlerle test et
elif test_case == "zero_values":
    try:
        rect = Rectangle(0, 5)
    except ValueError as e:
        print(f"Error creating rectangle: {e}")
    
    try:
        rect = Rectangle(5, 0)
    except ValueError as e:
        print(f"Error creating rectangle: {e}")

# Negatif değerlerle test et
elif test_case == "negative_values":
    rect = Rectangle(5, 3)
    original_dimensions = rect.dimensions
    
    try:
        rect.dimensions = (5, -3)
    except ValueError as e:
        print(f"Error setting dimensions: {e}")
    
    print(f"Dimensions after failed update: {rect.dimensions}")
    print(f"Original dimensions preserved: {rect.dimensions == original_dimensions}")

# Büyük değerlerle test et
elif test_case == "large_values":
    rect = Rectangle(1000000, 2000000)
    print(f"Large rectangle area: {rect.area}")
    print(f"Large rectangle perimeter: {rect.perimeter}")

# Kayan noktalı değerlerle test et
elif test_case == "float_values":
    rect = Rectangle(3.5, 2.75)
    print(f"Dimensions: {rect.dimensions}")
    print(f"Area: {rect.area}")
    print(f"Perimeter: {rect.perimeter}")
    
    rect.dimensions = (1.1, 2.2)
    print(f"New area with float dimensions: {rect.area}")

# Tür hatalarıyla test et
elif test_case == "type_errors":
    try:
        rect = Rectangle("5", 3)
    except Exception as e:
        print(f"Type error during creation: {type(e).__name__}: {e}")
    
    rect = Rectangle(5, 3)
    try:
        rect.dimensions = 10  # Demet değil
    except Exception as e:
        print(f"Type error setting dimensions: {type(e).__name__}: {e}")

# Birden fazla özellik işlemini test et
elif test_case == "property_operations":
    rect = Rectangle(5, 10)
    print(f"Initial - Width: {rect.width}, Height: {rect.height}, Area: {rect.area}")
    
    rect.width = 8
    print(f"After width change - Width: {rect.width}, Area: {rect.area}")
    
    rect.height = 6
    print(f"After height change - Height: {rect.height}, Area: {rect.area}")
    
    rect.dimensions = (12, 9)
    print(f"After dimensions change - Dimensions: {rect.dimensions}, Area: {rect.area}")
    
    del rect.dimensions
    print(f"After reset - Dimensions: {rect.dimensions}, Area: {rect.area}")

# Özellik doğrulamasının sınır durumlarını test et
elif test_case == "validation_edge_cases":
    rect = Rectangle(5, 3)
    
    try:
        rect.width = 0
    except ValueError as e:
        print(f"Zero width error: {e}")
    
    # Çok küçük bir pozitif değer kabul edilmeli
    rect.height = 0.0001
    print(f"Small height accepted: {rect.height}")
    print(f"Area with small height: {rect.area}")

# Birden fazla dikdörtgeni test et
elif test_case == "multiple_rectangles":
    rect1 = Rectangle(5, 3)
    rect2 = Rectangle(10, 2)
    rect3 = Rectangle(4, 4)
    
    print(f"Rectangle 1 - Area: {rect1.area}, Perimeter: {rect1.perimeter}")
    print(f"Rectangle 2 - Area: {rect2.area}, Perimeter: {rect2.perimeter}")
    print(f"Rectangle 3 - Area: {rect3.area}, Perimeter: {rect3.perimeter}")
    
    # Her dikdörtgeni değiştir
    rect1.width = 7
    rect2.height = 5
    rect3.dimensions = (6, 6)
    
    print(f"After modifications:")
    print(f"Rectangle 1 - Dimensions: {rect1.dimensions}")
    print(f"Rectangle 2 - Dimensions: {rect2.dimensions}")
    print(f"Rectangle 3 - Dimensions: {rect3.dimensions}")

# Çok sayıda işlemle performansı test et
elif test_case == "performance_test":
    rect = Rectangle(5, 5)
    
    # Çok sayıda özellik işlemi gerçekleştir
    for i in range(1000):
        rect.width = i % 10 + 1  # Değerler 1-10
        rect.height = i % 5 + 1  # Değerler 1-5
        area = rect.area  # Hesaplanan özelliğe eriş
        perimeter = rect.perimeter  # Hesaplanan özelliğe eriş
        dims = rect.dimensions  # Özellik getter'ına eriş
    
    print(f"Final state after 1000 operations:")
    print(f"Width: {rect.width}, Height: {rect.height}")
    print(f"Area: {rect.area}, Perimeter: {rect.perimeter}")
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