In Python, the @property decorator allows you to create "virtual" attributes — methods that look and behave like regular fields but implement the logic of a getter, setter, or deleter. This is useful for creating computed properties or controlling access to data.
Example:
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 (called as a property, not a function) r.width = 10 # setter is called automatically
Can you use only one @property (getter method) without defining a setter? What happens if you try to change such an attribute?
Answer: You can define only a getter @property without a setter (and deleter). Such an attribute will be read-only, and attempting to assign to it will raise AttributeError.
class C: @property def x(self): return 42 c = C() c.x = 99 # AttributeError: can't set attribute
Story
Tried to serialize an object using the standard library with vars(obj) to get a dictionary of attributes. It turned out that property methods are not included in the output of __dict__, and their values weren't serialized, leading to data leakage.
Story
In the project, we forgot to add a setter for the property, which led to a runtime error when trying to change the value of a computed field, although this was expected according to the architecture logic.
Story
In working code, the computation of the property value allowed heavy or unsafe operations, which were unexpectedly invoked each time the property was accessed. This reduced performance and led to blocking calls in multithreaded code.