Wyjaśnienie lekcji
@propertyPo tej lekcji będziesz potrafić:
@property.Python nie używa pól private w stylu Javy w ten sam sposób. Nazwa taka jak _balance sygnalizuje użytek wewnętrzny z konwencji; nie jest to silna ochrona dostępu. Właściwość pozwala zewnętrznemu kodowi odczytywać account.balance, podczas gdy metoda w tle oblicza lub waliduje wartość.
Zdefiniuj getter za pomocą @property. Dla właściwości z możliwością zapisu dodaj setter za pomocą @property_name.setter. Wewnątrz settera zapisuj do pola bazowego (self._balance), a nie do nazwy właściwości (self.balance), inaczej setter będzie wywoływał sam siebie w nieskończoność.
Właściwość może też być tylko do odczytu: pomiń jej setter. Właściwości obliczane powinny być spójne z bieżącym stanem obiektu. Używaj właściwości do sensownej walidacji lub obliczeń, a nie tylko po to, by odtwarzać rozbudowane gettery i settery z Javy.
_status przechowuje wartość, a status oferuje czysty interfejs odczytu.
class Task:
def __init__(self, status):
self._status = status
@property
def status(self):
return self._status
print(Task("queued").status)Wynik:
queuedSetter odrzuca wartości ujemne, zachowując poprzedni odczyt.
class Counter:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, next_value):
if next_value >= 0:
self._value = next_value
counter = Counter(3)
counter.value = -8
print(counter.value)Wynik:
3Nie trzeba synchronizować osobnego pola remaining.
class Quota:
def __init__(self, limit, used):
self.limit = limit
self.used = used
@property
def remaining(self):
return self.limit - self.used
quota = Quota(100, 35)
print(quota.remaining)Wynik:
65Używaj dostępu jak do atrybutu zamiast nawiasów; getter właściwości uruchamia się automatycznie.
class Release:
def __init__(self, passed):
self.passed = passed
@property
def ready(self):
return self.passed > 0
release = Release(2)
print(f"Ready: {release.ready}")Wynik:
Ready: True| Potrzeba | Użyj |
|---|---|
| Konwencja dla pola wewnętrznego | self._value |
| Publiczny dostęp do odczytu | Getter @property |
| Walidowany dostęp do zapisu | @value.setter |
| Wartość obliczana | Właściwość tylko do odczytu bez settera |
| Uniknięcie rekurencyjnych setterów | Przypisanie do pola bazowego, a nie self.value |
obj.total()) zamiast jej odczytu (obj.total).self.value = ... w setterze dla value._value jest niedostępne poza klasą; to tylko konwencja.