Properties & Decorators
Properties let you add getter/setter/deleter logic to attributes while keeping a clean attribute-style interface. Decorators modify function behavior.
@property
class Circle:
def __init__(self, radius):
self._radius = radius # private convention
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("Radius must be positive")
self._radius = value
@property
def area(self):
import math
return math.pi * self._radius ** 2
c = Circle(5)
print(c.radius) # 5
c.radius = 10 # calls setter
print(c.area) # 314.159...
# c.radius = -1 # raises ValueErrorWriting Decorators
import time, functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} ran in {end-start:.4f}s")
return result
return wrapper
@timer
def slow_sum(n):
return sum(range(n))
slow_sum(1_000_000)