In Python, @property is a built‑in decorator that lets you define computed attributes—attributes that look like ordinary data attributes when accessed, but whose values are actually produced by a method.
Why use it?
- Encapsulation – You can expose a clean, attribute‑style API while keeping the underlying implementation private or flexible.
- Read‑only or controlled write access – You can make an attribute read‑only, or run validation logic whenever it’s set or deleted.
- Lazy evaluation / caching – Compute a value only when it’s first needed, then store it for later accesses.
How it works
When you write:
class MyClass:
@property
def value(self):
# compute something
return self._value
Python does three things behind the scenes:
- The function
value is turned into a descriptor object of type property.
- That descriptor’s
__get__ method is called whenever you access obj.value. It runs the original function and returns its result.
- Because the descriptor lives on the class, you can also define
optional setter and deleter methods to control assignment and deletion.
Full pattern (getter, setter, deleter)
class Circle:
def __init__(self, radius):
self._radius = radius # “private” storage
@property
def radius(self):
"""Get the radius."""
return self._radius
@radius.setter
def radius(self, new_radius):
"""Validate and set a new radius."""
if new_radius < 0:
raise ValueError("Radius must be non‑negative")
self._radius = new_radius
@radius.deleter
def radius(self):
"""Delete the radius."""
del self._radius
Now you can interact with radius just like a normal attribute:
c = Circle(5)
print(c.radius) # → 5 (calls the getter)
c.radius = 10 # calls the setter, validates, updates _radius
del c.radius # calls the deleter
Common use‑cases
- Derived attributes: e.g.,
area computed from radius without storing it.
- Backward compatibility: expose a new method name while still supporting the old attribute‑style access.
- Read‑only constants: expose configuration values that shouldn’t be changed after initialization.
Quick recap
Decorator | Purpose
-- | --
@Property | Define the getter (read access).
@.setter | Define the setter (write access).
@.deleter | Define the deleter (delete access).
Using @property keeps your
objects’ public interface tidy and expressive, while still allowing you
to embed validation, lazy computation, or other logic under the hood.
In Python,
@propertyis a built‑in decorator that lets you define computed attributes—attributes that look like ordinary data attributes when accessed, but whose values are actually produced by a method.Why use it?
How it works
When you write:
Python does three things behind the scenes:
valueis turned into a descriptor object of typeproperty.__get__method is called whenever you accessobj.value. It runs the original function and returns its result.Full pattern (getter, setter, deleter)
Now you can interact with
radiusjust like a normal attribute:Common use‑cases
areacomputed fromradiuswithout storing it.Quick recap
Using
@propertykeeps your objects’ public interface tidy and expressive, while still allowing you to embed validation, lazy computation, or other logic under the hood.