This Python Encapsulation lesson is for a beginner. Read the short notes, run each example, then change one name or number and run it again.
Encapsulation keeps the inner details behind a small set of methods. A single leading underscore, _seats, tells other programmers the attribute is internal.
Python will not stop outside code from reading it. The underscore is a warning, not a lock. Two leading underscores trigger name mangling.
Example 1: Start here
Expose book() and a read method. Let the storage stay an internal detail.
class Batch: # a template for objects
def __init__(self): # runs when you create the object
self._seats = 0 # store this on the object
def book(self): # define the function; it runs when you call it
self._seats += 1 # update the stored value
return self._seats # send this value back to the caller
print(Batch().book())
Example 2: A convention with an underscore
A single underscore says other code should use the method, not the raw attribute.
class Course: # a template for objects
def __init__(self, seats): # runs when you create the object
self._seats = seats # store this on the object
def seats(self): # define the function; it runs when you call it
return self._seats # send this value back to the caller
print(Course(24).seats())
Example 3: Name mangling
Two leading underscores make the attribute harder to reach from outside the class.
class Course: # a template for objects
def __init__(self): # runs when you create the object
self.__seats = 24 # store this on the object
def seats(self): # define the function; it runs when you call it
return self.__seats # send this value back to the caller
print(Course().seats())
Example 4: Change it through a method
The method can reject a bad change before it stores the number.
class Course: # a template for objects
def __init__(self): # runs when you create the object
self._seats = 20 # store this on the object
def add(self, more): # define the function; it runs when you call it
if more > 0: # run the indented lines only when this is true
self._seats += more # update the stored value
def seats(self): # define the function; it runs when you call it
return self._seats # send this value back to the caller
course = Course() # one object
course.add(4)
print(course.seats())
