Direct attribute access keeps a moving rectangle easy to read, but its coordinates still need boundary checks. Python property decorators put that behavior in methods without forcing callers to switch to explicit getter and setter calls. section 4.1.2
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if not (0 < value < SCREEN_WIDTH - self.width):
self.dir_x = -self.dir_x
self._x += abs(self._x - value) * self.dir_x
The `@property` method reads `x`; the `@x.setter` method handles a proposed value and reverses direction when it crosses a screen boundary. section 4.1.2
Decorators can also add behavior around a function call. A timing decorator returns a wrapper that starts a timer, calls the original function, reports elapsed time, and returns the result. Placing `@timing_decorator` above a function applies that wrapper while leaving the function’s body unchanged. section 4.1.2






