Właściwości (property) w Pythonie powstały jako sposób eleganckiego wdrażania enkapsulacji atrybutów, analogicznie do getterów i setterów z innych języków (Java/C++), ale bez konieczności jawnego wywoływania metod. Przed wprowadzeniem property, dostęp do zmiennych musiał być realizowany przez jawne metody get/set, co utrudniało i zanieczyszczało interfejs klasy.
Problem polega na tym, aby użytkownik klasy miał przejrzysty interfejs pracy z atrybutami (używając notacji kropkowej obj.x), a wewnątrz można było kontrolować logikę obliczania, sprawdzania, buforowania lub walidacji wartości. Bez property, przy zmianie wewnętrznej implementacji, trzeba zmieniać wszystkie wywołania, co prowadzi do masowych błędów i obniża skalowalność.
Rozwiązanie — dekorator @property pozwala przekształcić metodę w atrybut i jednocześnie ukryć logikę obliczania, sprawdzania lub leniwą ładowanie wewnątrz metod, nie zmieniając zewnętrznego interfejsu klasy. Getter realizuje dostęp tylko do odczytu, za pomocą .setter organizuje zapis, a .deleter — usunięcie.
Przykład kodu:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): # 'area' można teraz odczytywać jako atrybut return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): # automatycznie wywoływane przy przypisaniu rect.width = ... assert value > 0, "Szerokość musi być dodatnia" self._width = value rect = Rectangle(3, 4) print(rect.area) # 12 rect.width = 10 print(rect.area) # 40
Kluczowe cechy:
Czy property może działać z metodami klasowymi lub statycznymi?
Nie. property realizuje tylko właściwości na poziomie instancji. Do właściwości na poziomie klasy użyj specjalnych deskryptorów lub @classmethod-property (wdrażane ręcznie).
Jeśli zadeklaruję property tylko z getterem bez settera, czy będzie można zapisać w atrybucie?
Nie. Taka property jest tylko do odczytu; próba przypisania spowoduje AttributeError.
Co się stanie, jeśli wewnątrz setter'a wystąpi wyjątek (np. assert)?
Wyjątek zostanie podniesiony na zewnątrz, przypisanie nie dojdzie do skutku, a wartość atrybutu pozostanie niezmieniona. Często używane do walidacji.
Negatywny przypadek: Publiczne atrybuty klasy, zmiana ich bez kontroli.
Zalety: szybko, prosto.
Wady: nie można zmienić wewnętrznej logiki bez przepisywania kodu klienta, możliwe niespójne stany.
Pozytywny przypadek: Enkapsulacja przez property, logika w getterze/setterze, ścisłe kontrole.
Zalety: elastyczność, kontrola, przejrzystość, bezpieczna ewolucja API.
Wady: nieco więcej kodu, niewielkie skomplikowanie w debugowaniu.