Python Properties · Examples
Object-Oriented Python

Python Properties Examples

Short, runnable programs that show python @property: getters and setters in action. Read the explanation, press Run, then change the code and try your own ideas. New to the topic? Start with the Python @property: Getters and Setters lesson.

1A computed attribute that is always up to date

duration is not stored. It is added up from the songs every time you read it, so it is correct after each add() call and can never drift out of sync.

A computed attribute that is always up to date
class Playlist:
    def __init__(self, name):
        self.name = name
        self.songs = []              # list of (title, seconds)

    def add(self, title, seconds):
        self.songs.append((title, seconds))

    @property
    def duration(self):
        total = sum(seconds for _, seconds in self.songs)
        return f"{total // 60}:{total % 60:02d}"

mix = Playlist("Focus")
mix.add("Intro", 95)
print(mix.duration)
mix.add("Deep Work", 250)
print(mix.duration)
Expected output1:35
5:45

2A setter with clear error messages

The setter can reject a wrong type (TypeError) and a wrong value (ValueError) with different messages. The loop shows that a refused value leaves the old price in place.

A setter with clear error messages
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 not isinstance(value, (int, float)):
            raise TypeError("price must be a number")
        if value < 0:
            raise ValueError("price cannot be negative")
        self._price = value

item = Product("Lamp", 40)
for new_price in [35, -5, "free"]:
    try:
        item.price = new_price
        print("Price is now", item.price)
    except (ValueError, TypeError) as err:
        print(type(err).__name__ + ":", err)
print("Final price:", item.price)
Expected outputPrice is now 35
ValueError: price cannot be negative
TypeError: price must be a number
Final price: 35

3A setter that cleans the data

A setter can also fix up the value before storing it. Here every username is trimmed and lower-cased, and an empty one is refused, so the rest of the program can rely on tidy data.

A setter that cleans the data
class Account:
    def __init__(self, username):
        self.username = username

    @property
    def username(self):
        return self._username

    @username.setter
    def username(self, value):
        cleaned = value.strip().lower()
        if not cleaned:
            raise ValueError("username cannot be empty")
        self._username = cleaned

user = Account("  PixelFan  ")
print(repr(user.username))
user.username = "ASHA"
print(user.username)
try:
    user.username = "   "
except ValueError as err:
    print("Error:", err)
Expected output'pixelfan'
asha
Error: username cannot be empty

4Compute once with cached_property

functools.cached_property runs the method the first time and keeps the answer on the object. The counter proves it ran once. If the data changes, del r.average forgets the cached value so the next read recalculates.

Compute once with cached_property
from functools import cached_property

class Report:
    def __init__(self, numbers):
        self.numbers = numbers
        self.calculations = 0

    @cached_property
    def average(self):
        self.calculations += 1
        return sum(self.numbers) / len(self.numbers)

r = Report([80, 90, 100])
print(r.average, r.average, r.average)
print("Calculated", r.calculations, "time(s)")
r.numbers.append(60)
del r.average
print(r.average, r.calculations)
Expected output90.0 90.0 90.0
Calculated 1 time(s)
82.5 2

5Read-only properties protect values

An order number should never change after creation. With only a getter, any attempt to assign raises AttributeError, and the value stays safe.

Read-only properties protect values
class Order:
    def __init__(self, order_id):
        self._order_id = order_id

    @property
    def order_id(self):
        return self._order_id

order = Order(1042)
print(order.order_id)
try:
    order.order_id = 7
except AttributeError as err:
    print("Blocked:", err)
print(order.order_id)
Expected output1042
Blocked: property 'order_id' of 'Order' object has no setter
1042

Practise next

Python @property: Getters and Setters exercises → Back to the lesson

Python Class Attributes vs Instance Attributes examplesPython Encapsulation: Public, Protected and Private examplesPython Dunder (Magic) Methods examples