Decorating a method with @property turns calling it into simple attribute access, with no parentheses needed, which lets you expose a value that's actually computed on demand, while still looking exactly like a plain stored attribute from the outside. Paired with a corresponding setter method, a property can also validate or transform a value on assignment, letting you add that logic to an existing class later without breaking any code that already accesses the attribute directly, since the calling syntax stays identical whether it's a plain attribute or a property.
1Understanding Property Decorator (@property)
Decorating a method with @property turns calling it into simple attribute access, with no parentheses needed, which lets you expose a value that's actually computed on demand, while still looking exactly like a plain stored attribute from the outside. Paired with a corresponding setter method, a property can also validate or transform a value on assignment, letting you add that logic to an existing class later without breaking any code that already accesses the attribute directly, since the calling syntax stays identical whether it's a plain attribute or a property.
@property is especially valuable for adding validation to an attribute retroactively — you can start with a plain public attribute, and later convert it to a property with a setter that validates input, without changing a single line of code that already assigns to that attribute.
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return round(3.14159 * self.radius ** 2, 2)
c = Circle(5)
print(c.area)2Practical Example
Here is a real-world application of Property Decorator (@property) showing how it is used in production Python code.
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("Below absolute zero")
self._celsius = value
t = Temperature(20)
t.celsius = 25
print(t.celsius)3Best Practices
Follow these guidelines when working with Property Decorator (@property):
1. Use @property for attributes that are actually computed from other state, so they stay in sync automatically instead of needing manual updates
2. Add a matching setter when the property should also support validated assignment, not just read access
3. Avoid doing expensive or side-effecting work inside a property getter — callers expect attribute access to be fast and free of surprises, the same as a plain attribute
Tip: @property is especially valuable for adding validation to an attribute retroactively — you can start with a plain public attribute, and later convert it to a property with a setter that validates input, without changing a single line of code that already assigns to that attribute.
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return round(3.14159 * self.radius ** 2, 2)
c = Circle(5)
print(c.area)