Properties and Class Methods
The @property decorator
Section titled “The @property decorator”@property turns a method into an attribute-style accessor.
Callers use obj.celsius instead of obj.get_celsius(), keeping the public API clean while allowing validation logic to run behind the scenes.
class Temperature: def __init__(self, celsius: float = 0.0) -> None: self._celsius = celsius # underscore = internal storage
@property def celsius(self) -> float: return self._celsiusSetters
Section titled “Setters”Pair @property with @name.setter to intercept assignment:
@celsius.setter def celsius(self, value: float) -> None: if value < -273.15: raise ValueError("Temperature below absolute zero!") self._celsius = valueNow t.celsius = -300 raises ValueError automatically.
Without a setter, the property is read-only — attempts to assign raise AttributeError.
Computed (derived) properties
Section titled “Computed (derived) properties”A property can compute its value on the fly with no backing storage:
@property def fahrenheit(self) -> float: return self._celsius * 9 / 5 + 32t.fahrenheit looks like a plain attribute to the caller, but it is recalculated each time.
@classmethod — alternative constructors
Section titled “@classmethod — alternative constructors”A class method receives the class (cls) as its first argument instead of the instance.
The most common use is providing alternative constructors:
@classmethod def from_fahrenheit(cls, f: float) -> "Temperature": return cls((f - 32) * 5 / 9)boiling = Temperature.from_fahrenheit(212)print(boiling.celsius) # 100.0Subclasses automatically inherit the class method and cls will refer to the subclass — so the factory creates an instance of the correct type.
@staticmethod — utility functions
Section titled “@staticmethod — utility functions”A static method receives neither the instance nor the class. Use it for utilities that logically belong to the class but do not need access to class or instance state:
@staticmethod def absolute_zero() -> float: return -273.15print(Temperature.absolute_zero()) # -273.15Full runnable demo
Section titled “Full runnable demo”class Temperature: def __init__(self, celsius: float = 0.0) -> None: self._celsius = celsius
@property def celsius(self) -> float: return self._celsius
@celsius.setter def celsius(self, value: float) -> None: if value < -273.15: raise ValueError("Temperature below absolute zero!") self._celsius = value
@property def fahrenheit(self) -> float: return self._celsius * 9 / 5 + 32
@classmethod def from_fahrenheit(cls, f: float) -> "Temperature": return cls((f - 32) * 5 / 9)
@staticmethod def absolute_zero() -> float: return -273.15
t = Temperature(100)print(t.celsius)print(t.fahrenheit)t.celsius = 0print(t.fahrenheit)t2 = Temperature.from_fahrenheit(212)print(t2.celsius)print(Temperature.absolute_zero())Loading Python runtime (first run only)…