Properties, Class & Static Methods

Properties let you run code when an attribute is read or written, while keeping simple obj.attr syntax. Class methods work on the class itself — the standard way to write alternative constructors. Static methods are plain functions that live inside a class for organisation.

Properties: computed attributes

PY computed.py
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

r = Rectangle(3, 4)
print(r.area)
r.width = 10
print(r.area)
Output
12
40

@property turns a method into a read-only attribute — accessed without parentheses and always up to date.

Validating with a setter

PY setter.py
class Thermostat:
    def __init__(self, celsius=20):
        self.celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if not 5 <= value <= 30:
            raise ValueError(f"{value}°C is out of range (5–30)")
        self._celsius = value

    @property
    def fahrenheit(self):
        return self._celsius * 9 / 5 + 32

t = Thermostat()
t.celsius = 25
print(t.celsius, t.fahrenheit)

try:
    t.celsius = 99
except ValueError as err:
    print(err)
Output
25 77.0
99°C is out of range (5–30)

The real value lives in _celsius; the property controls access. Note that __init__ assigns through the property too, so invalid starting values are rejected as well.

A great benefit: you can start with a plain attribute and later turn it into a property with validation, without changing any code that uses the class.

Read-only attributes

PY read_only.py
class Order:
    def __init__(self, order_id):
        self._id = order_id

    @property
    def id(self):
        return self._id

o = Order(42)
print(o.id)
o.id = 7
Output
42
Traceback (most recent call last):
  File "main.py", line 11, in <module>
    o.id = 7
    ^^^^
AttributeError: property 'id' of 'Order' object has no setter

Class methods: alternative constructors

A @classmethod receives the class (conventionally cls) instead of an instance. Its main use is creating objects in different ways:

PY classmethod.py
from datetime import date

class Person:
    def __init__(self, name, birth_year):
        self.name = name
        self.birth_year = birth_year

    @classmethod
    def from_string(cls, text):
        name, year = text.split(",")
        return cls(name.strip(), int(year))

    @classmethod
    def from_age(cls, name, age, today=date(2026, 10, 6)):
        return cls(name, today.year - age)

    def __repr__(self):
        return f"Person({self.name!r}, {self.birth_year})"

print(Person.from_string("Ada, 1815"))
print(Person.from_age("Ben", 30))
Output
Person('Ada', 1815)
Person('Ben', 1996)

Using cls(...) instead of Person(...) means subclasses get instances of the subclass. You've seen this pattern in the standard library: dict.fromkeys(), datetime.fromisoformat(), int.from_bytes().

Class methods for shared state

PY counter.py
class Ticket:
    issued = 0

    def __init__(self):
        Ticket.issued += 1
        self.number = Ticket.issued

    @classmethod
    def reset(cls):
        cls.issued = 0

a, b, c = Ticket(), Ticket(), Ticket()
print(c.number, Ticket.issued)
Ticket.reset()
print(Ticket().number)
Output
3 3
1

Static methods

A @staticmethod receives neither the instance nor the class. It's just a function grouped with the class because it's related:

PY staticmethod.py
class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

    @staticmethod
    def c_to_f(c):
        return c * 9 / 5 + 32

    def describe(self):
        return f"{self.celsius}°C = {self.c_to_f(self.celsius)}°F"

print(Temperature.c_to_f(100))
print(Temperature(37).describe())
Output
212.0
37°C = 98.6°F

In Python, a plain module-level function is often just as good. Use a static method when the function clearly belongs to the class's concept.

Which kind of method?

KindFirst parameterUse for
Instance methodself (the object)Behaviour that uses or changes an object's data — most methods
@classmethodcls (the class)Alternative constructors, class-wide state
@staticmethodnoneHelpers related to the class that need no object or class data
@propertyselfComputed or validated attributes

Try it yourself

Try it yourself
Console output