Wren pins yesterday's output to the board: battery -40, facing up. "What does the evidence say?" he asks. "Any line of code anywhere could do that to Pip."
Comet frowns. "So we lock the battery away? Then how does anyone read it?"
Nova projects Pip inside a box with a few small windows. "How can I help?" she asks. "Keep the values inside. Open a window, a method, for each thing outside code may ask."
Comet sketches the windows in her notebook. "get_row, get_col, get_heading, get_battery. Lead programmer, let's build them."
Encapsulation keeps a class's details hidden from other classes. Access to attributes should stay inside the class.
Python has no truly private variables. By convention, a name that starts with an underscore, like _battery, is not part of the public interface. Other code should leave it alone.
# rover_hidden.py
class Rover:
"""A survey rover on the Larkspur test field."""
def __init__(self, name, row=0, col=0):
self.name = name
self._row = row
self._col = col
self._heading = "E"
self._battery = 100
def get_row(self):
return self._row
def get_battery(self):
return self._battery
def status(self):
return (f"{self.name} at ({self._row}, {self._col}) facing "
f"{self._heading}, battery {self._battery}")
pip = Rover("Pip")
dot = Rover("Dot", 2, 3)
print(pip.status())
print(dot.status())
print(dot.get_row(), pip.get_battery()) Pip at (0, 0) facing E, battery 100 Dot at (2, 3) facing E, battery 100 2 100
An accessor method lets other code read a value without reaching into the object. Here b = 0 only points the name b at a new number. It does not reach back into Pip. A list is different: week 4 shows why get_samples() must hand back a copy on purpose.
# accessor_copy.py
from rover_hidden_class import Rover
pip = Rover("Pip")
b = pip.get_battery()
b = 0
print(b, pip.get_battery()) # underscore.py
from rover_hidden_class import Rover
pip = Rover("Pip")
pip._battery = -40
print(pip.status()) The crew's rule from now on: outside code never touches a name that starts with an underscore. It calls methods instead.
| Statement | True or false? |
|---|---|
| Encapsulation keeps a class's details hidden from other classes. | ? |
| A name starting with an underscore cannot be changed from outside. | ? |
| An accessor gives back a value without letting other code set the instance variable directly. | ? |
| Outside code should read Pip's battery through get_battery(). | ? |
Pip's state now sits behind methods. Tomorrow is Sim Lab: the real rover.py, with turns.