A property intercepts attribute access so a class can enforce a rule when a value is read or assigned.
Python properties: validate mutation at the public attribute boundary
Operation contract
StockItem accepts a nonnegative integer quantity and uses the same property setter during construction and later updates. A rejected update leaves the old quantity intact because validation runs before assignment. Direct-field mutation would otherwise bypass a public method-only rule.
Failure and ownership boundary
The underscore-prefixed storage is a convention, not an authorization barrier. Code with access to the object can still reach its backing attribute. The property also supplies no lock or multi-field transaction. Python inventory project: validate a batch before replacing stored state must validate the whole operation before committing a state change.
Working program
class StockItem:
def __init__(self, quantity):
self.quantity = quantity
@property
def quantity(self):
return self._quantity
@quantity.setter
def quantity(self, value):
if type(value) is not int or value < 0:
raise ValueError("nonnegative integer required")
self._quantity = value
stock = StockItem(8)
try:
stock.quantity = -1
except ValueError:
print("update rejected")
print(stock.quantity)Output
update rejected
8Costs and limits
The fixture performs bounded scalar validation. A setter touching external storage or several fields needs its own failure and atomicity contract.
Common Mistakes
- Validate before replacing stored state.
- An underscore is not access control.
Connected lessons
Python classes: keep instance state separate from class state, Python inventory project: validate a batch before replacing stored state, Java encapsulation and object ownership.
Apply this boundary
Python descriptors: field validation and attribute precedence.
