A moving rectangle needs readable position updates, but its coordinates must stay within the screen. Ordinary getter and setter methods can control those updates, though calls such as `rectangle.set_x(rectangle.get_x() + 1)` obscure the simple movement. Properties keep `rectangle.x += 1` while putting the control inside the class. 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 assignments to `x`, reversing horizontal direction when the requested position crosses a screen boundary. section 4.1.2
The underscore in `_x` signals that callers should use the property, not the stored attribute directly; it does not enforce privacy. Use a property when an attribute needs behavior without making callers switch to method-call syntax. section 4.1.2

