PythiloLesson 8 of 30 · progress kept in this browser

Properties

Start classes with plain attributes. When a value later needs checking or computing, @property turns the attribute into method calls without changing how callers read or assign it.

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

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("negative")
        self._radius = value

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

c = Circle(2)
c.radius = 3
print(c.radius, round(c.area, 2))
  • The decorated method is the getter, and @radius.setter adds assignment under the same name.
  • The real value lives under another name, by convention _radius. Assigning self.radius inside the setter would call the setter again, forever.
  • A property without a setter is read-only, so assigning to c.area raises AttributeError.
  • Assigning in __init__ goes through the setter, so construction is validated too.

Keep getters cheap and free of side effects. Callers expect reading an attribute to be quick and harmless.

Your task

Write Temperature(celsius) where celsius is a property whose setter raises ValueError below -273.15, including in __init__. Add a fahrenheit property with a setter that stores the matching Celsius value, and a read-only kelvin property.