Menu
Coddy logo textTech

İ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, siliciler ve tam özellik yönetimi de dâhil olmak üzere öznitelik erişimi üzerinde daha gelişmiş denetim sağlar.

Aşağıda, değerleri diğer özniteliklerden türeten hesaplanmış özelliklere bir örnek verilmiştir:

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)

Hesaplanmış özellikleri normal öznitelikler gibi kullanın:

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

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

Tam özellik işlevselliğini kullanın:

temp = Temperature()

Doğrulama ile setter'ı kullanın:

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

# temp.temperature = -300  # ValueError fırlatırdı

Siliciyi kullanın:

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}")  # Skor: 2500, Seviye: 3

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

Çıktı:

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

Temel Nokta: Gelişmiş özellik dekoratörleri, hesaplanan ö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 görevde, 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ıdır)
    • TODO'larda belirtildiği şekilde uygun ValueError mesajlarını oluştur
    • Önemli: Değerin 0'a eşit veya 0'dan küçük olup olmadığını kontrol et, ardından hatayı oluştur (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şlevselliğine sahip bir dimensions özelliği oluştur
    • Önemli: Ayarlayıcıda demet açma söz dizimini 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}")
    
    # Test the dimensions property
    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
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
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
elif test_case == "large_values":
    rect = Rectangle(1000000, 2000000)
    print(f"Large rectangle area: {rect.area}")
    print(f"Large rectangle perimeter: {rect.perimeter}")

# Kayan nokta değerleriyle test
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}")

# Tip hatalarıyla test
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  # Bir tuple 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ğrulama kenar 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 pozitif değer kabul edilmelidir
    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  # Hesaplanmış özelliğe eriş
        perimeter = rect.perimeter  # Hesaplanmış ö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