Codectionary / Developer documentation / Python

@property

The @property decorator lets you define a method that can be accessed like a plain attribute, without parentheses. This is useful for computed values that should look like simple attributes, and for adding validation logic that runs whenever an attribute is set, via a matching @x.setter. Properties let you start with simple public attributes and later add logic without breaking any code that uses the class.

Syntax

@property\ndef attr(self):\n    return self._attr

Examples

Basic Property

Exposing a computed value that looks like a regular attribute.

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def area(self):
        return 3.14159 * self.radius ** 2

c = Circle(5)
print(c.area)  # 78.53975 (called without parentheses, like an attribute)

Property with a Setter

Adding validation logic that runs whenever the attribute is assigned to.

class Product:
    def __init__(self, name, price):
        self.name = name
        self._price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError("Price cannot be negative")
        self._price = value

item = Product("Mouse", 25)
item.price = 30       # calls the setter
print(item.price)     # 30

try:
    item.price = -10  # raises ValueError
except ValueError as e:
    print(e)

Read-Only Property

Defining a property with no setter to make it effectively read-only from outside the class.

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last

    @property
    def full_name(self):
        return f"{self.first} {self.last}"

emp = Employee("John", "A")
print(emp.full_name)  # John A

# emp.full_name = "New Name"  # would raise AttributeError - no setter defined

Best practices

  • Use @property for computed or derived values that should behave like attributes, not method calls with parentheses
  • Add a @x.setter only when you need validation or side effects on assignment - a plain attribute is simpler when no logic is needed
  • Store the underlying data in a conventionally "private" attribute (prefixed with an underscore) to avoid naming conflicts with the property itself
  • Start a class with plain public attributes, and convert to a property later if you need to add logic - this keeps the external interface unchanged

Runtime & versions

Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Python language reference

Specifications & further reading