Python OOP Tutorial 6: Property Decorators - Getters, Setters, and Deleters
Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Use `@property` to expose a computed value (like `email`) through attribute syntax while recalculating from current underlying fields.
Briefing
Property decorators in Python let class attributes behave like computed fields—readable like normal attributes, while still backed by methods that can calculate values on demand. The practical payoff shows up immediately with an `Employee` example where `email` depends on `first_name` and `last_name`. After changing `first_name`, the stored `email` becomes stale, even though a `full_name` method stays correct by recomputing from the latest names each time it runs.
A naive fix—turning `email` into a method—would keep the value up to date, but it forces every existing caller to change from `employee.email` to `employee.email()` (adding parentheses). That breaks compatibility with code written against the original attribute-style API. The property decorator solves this by allowing a method to be accessed using attribute syntax. By defining an `email` method and decorating it with `@property`, the code can keep calling `employee.email` while the method still recomputes `first_name + '.' + last_name + '@email.com'` every time it’s accessed.
The tutorial then extends the same idea to assignment. With only `@property`, attempting to set `employee.full_name = 'Quarry Schaefer'` raises an error because properties are read-only unless a setter is added. The fix is another decorator: `@full_name.setter`. That setter method uses the incoming string, splits it on the space into first and last components, and writes them back to `self.first` and `self.last`. Once those underlying fields update, dependent computed properties like `email` automatically reflect the new names.
Finally, a deleter demonstrates cleanup behavior. Using `@full_name.deleter`, the code runs custom logic when `del employee.full_name` is called—here, it prints a message and sets `self.first` and `self.last` to `None`. The overall pattern is that `@property` provides attribute-style access for computed values, `@<property>.setter` enables controlled updates through assignment, and `@<property>.deleter` supports custom teardown logic.
The key takeaway is compatibility: done correctly, property decorators let users keep the same attribute access patterns while the class gains getter/setter/deleter functionality internally. The tutorial also warns that changing an existing method into an attribute can be risky if other code already depends on the old calling style, so the benefits come with the need for careful API design.
Cornell Notes
Python’s `@property` decorator turns a method into an attribute-like interface, enabling computed values to stay consistent with underlying data. In the `Employee` example, `email` is derived from `first_name` and `last_name`, so storing it directly causes staleness when names change. Decorating an `email` method with `@property` keeps callers using `employee.email` while recalculating the address on access. To support assignment like `employee.full_name = 'Quarry Schaefer'`, a matching `@full_name.setter` parses the input and updates `first` and `last`. A `@full_name.deleter` runs cleanup code when `del employee.full_name` is called.
Why does `email` become incorrect after changing `first_name` in the initial `Employee` setup?
Why is converting `email` into a plain method not a drop-in fix?
How does `@property` let a method be accessed like an attribute?
What happens when trying to assign to a property that only has `@property`, and how is it fixed?
How does a deleter work for properties, and what cleanup does the example perform?
Review Questions
- In the `Employee` example, what specific change prevents `email` from going stale when `first_name` or `last_name` changes?
- What error occurs when assigning to a property that only has `@property`, and which decorator resolves it?
- How does the `full_name` setter transform the assigned string into updates for `first` and `last`?
Key Points
- 1
Use `@property` to expose a computed value (like `email`) through attribute syntax while recalculating from current underlying fields.
- 2
Avoid breaking existing code by not replacing `employee.email` with `employee.email()`; `@property` preserves the original access pattern.
- 3
Properties are read-only by default; assignment requires adding a setter with `@<property>.setter`.
- 4
A setter can parse assigned input (e.g., splitting a full name on a space) and update the underlying fields that drive other computed properties.
- 5
A deleter with `@<property>.deleter` runs custom cleanup logic when `del instance.<property>` is called.
- 6
Changing a method into an attribute can affect callers, so property-based API changes should be done carefully for compatibility.