programowanieProgramista Python

Czym są adnotowane atrybuty (property) w Pythonie, jak działa wbudowany dekorator @property i po co (i kiedy) go używa się? Podaj przykłady i opowiedz o typowych błędach przy pracy z property.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W Pythonie dekorator @property umożliwia tworzenie atrybutów "wirtualnych" — metod, które wyglądają i działają jak zwykłe pola, ale wykonują logikę getterów, setterów lub deleterów. Jest to wygodne dla tworzenia właściwości obliczeniowych lub kontrolowania dostępu do danych.

Przykład:

class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): if value <= 0: raise ValueError('Width must be positive') self._width = value r = Rectangle(3, 4) print(r.area) # 12 (wywoływane jak właściwość, nie funkcja) r.width = 10 # setter wywołany automatycznie

Pytanie z podstępem.

Czy można używać tylko jednego @property (metody get), nie definiując settera? Co się stanie, jeśli spróbujesz zmienić taki atrybut?

Odpowiedź: Można zdefiniować tylko getter @property bez settera (i deletera). Taki atrybut będzie tylko do odczytu, a próba przypisania spowoduje AttributeError.

class C: @property def x(self): return 42 c = C() c.x = 99 # AttributeError: can't set attribute

Przykłady rzeczywistych błędów spowodowanych brakiem znajomości subtelności tematu.


Historia

Próbowano zserializować obiekt za pomocą standardowej biblioteki, używając vars(obj), aby uzyskać słownik atrybutów. Okazało się, że metody property nie wchodzą w wynik __dict__, ich wartości nie były serializowane, co prowadziło do wycieku danych.


Historia

W projekcie zapomniano dodać settera dla property, w efekcie próba zmiany wartości obliczanego pola prowadziła do błędu w czasie wykonywania, chociaż z logiką architektury to było oczekiwane.


Historia

W działającym kodzie obliczenie wartości właściwości umożliwiało ciężkie lub niebezpieczne operacje, które niespodziewanie były wywoływane przy każdym dostępie do właściwości. To obniżyło wydajność i prowadziło do blokujących wywołań w kodzie wielowątkowym.