ProgramlamaBackend geliştirici

Python'da özellik dekoratörleri (@property) nedir, nasıl kapsüllemeyi gerçekleştirmeye yardımcı olurlar ve kullanırken hangi tuzaklar vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Konu tarihi:

Klasik OOP'de kapsülleme, özel alanlar ve getter/setter'lar aracılığıyla gerçekleştirilir; bu, hantal ve "Python tarzı" değildir. Python 2.2 sürümünden itibaren, yöntemlere normal öznitelikler gibi erişim sağlayan @property dekoratörü ortaya çıkmıştır, böylece düzgün kapsülleme sağlanır ve kullanışlı bir sözdizimi sunar.

Sorun:

Property dekoratörleri olmadan, erişim ve değer ayarlama yöntemlerini açıkça tanımlamak gerekir (örneğin, get_x() ve set_x(val)), bu da kodun okunabilirliğini azaltır ve sınıf kullanıcıları iç verilerine doğrudan erişimden korunmaz. Yeniden yapılandırma ve iç değerlerin saklanma veya hesaplama mantığında değişiklik yapma sorunları ortaya çıkar.

Çözüm:

@property dekoratörü, getter'lar, setter'lar ve deleter'lar tanımlamayı tek bir sözdizimiyle yapmayı sağlar. Bu, şık görünür, kullanışlıdır ve uygulama detaylarını kapsüller ve özelliğin hesaplama şeklini sınıf arayüzünü bozmayacak şekilde değiştirmeye olanak tanır.

Kod örneği:

class Temperature: def __init__(self, celsius): self._celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("-273.15°C'nin altındaki sıcaklık mümkün değildir!") self._celsius = value

Temel özellikler:

  • @property dekoratörü, yöntemlere normal öznitelikler gibi erişim sağlar.
  • Doğrulama veya önbellekleme mantığı eklemek kolaydır.
  • Arayüz değişmeden mantığı değiştirmek — sınıf kullanıcıları değişiklikleri fark etmez.

İkna edici sorular.

Sadece okumaya, ancak yazmaya/silme için olmayan bir özellik yapabilir misiniz?

Evet, sadece @property dekoratörü ile bir yöntem tanımlanırsa, özellik yalnızca okunabilir hale gelir.

class Sample: @property def value(self): return 42

Eğer property adı özel bir öznitelikle aynıysa ne olur?

Genellikle property, alt çizgi ile başlayan özel bir özniteliğe "ara katman" olarak kullanılır (örneğin, _x). Bu tür bir çakışmadan kaçınılmalıdır; aksi takdirde, rekürsif bir çağrı oluşur:

class Bad: @property def x(self): return self.x # Sonsuz rekürsiyon

Sadece sınıf için property atayabilir misiniz?

Hayır, standart @property sınıf örnekleriyle çalışır. Sınıf özelliği oluşturmak için dış tasarım desenleri veya özel kütüphaneler kullanmak gerekir (property ile birlikte @classmethod doğrudan çalışmaz).

Tipik hatalar ve anti-patentler

  • Özniteliklerin yanlış adlandırılması (örneğin, property adı ve iç alanın tekrar edilmesi).
  • Yanlış uygulanmış setter, rekürsif bir çağrıya neden olur.
  • Hesaplama/doğrulama gerektirmeyen özellikler için property kullanımından aşırı yararlanma.

Gerçek yaşam örneği

Olumsuz durum

Geliştirici, sınıf alanına (self.celsius) doğrudan erişiyor, property üzerinden değil. Daha sonra doğrulama ekleniyor, ancak sınıf kullanıcıları hala özel özniteliği doğrudan değiştirebilir ve kontrolleri atlayabilir.

Artılar:

Karmaşık bir mantık yokken çalışmak kolay ve hızlı.

Eksiler:

Kapsülleme ihlal edildi, nesnenin hatalı bir durumda olması kolay, karmaşa ortaya çıkıyor.

Olumlu durum

Property kullanımı ve iç özniteliğin _celsius ile gizlenmesi. Doğrulama, önbellekleme ve mantık, property içinde merkezileşir.

Artılar:

Kod korumalıdır, arayüz istikrarlıdır — özellik uygulamasını değiştirmek kullanıcılar üzerinde etki yaratmaz.

Eksiler:

Büyük ve karmaşık nesnelerde, property'yi aşırı kullanırsanız, hata ayıklama karmaşıklığını artırabilir.