Encapsulation - Introduction To Encapsulation
Encapsulation - Introduction To Encapsulation
Encapsulation
Introduction to Encapsulation
Learning Objectives
What is Encapsulation?
Encapsulation is a concept in which related data and methods are grouped
together, and in which access to data is restricted. Grouping related data
and methods makes thinking about your program a bit easier. Hiding or
restricting how the user interacts with the data can keep the user from
making unwanted changes. Encapsulation is not unique to Python, but the
ways in which each programming language implement encapsulation are
a bit different.
The two main ideas of data restriction are public and private. These
adjectives can refer to both attributes and methods. Public means that the
attribute or method can be accessed by an instance of a class. Private
means that the attribute or method can only be accessed by the class itself.
Classes as Encapsulation
Classes in Python are a form of encapsulation; they group together related
data and methods. In the image below, the attributes num1 and num2 are
grouped together with the methods describe and sum. They are all a part of
ExampleClass (highlighted in red). The instance my_example is not a part of
the class itself; it is considered to be separate.
Classes as Encapsulation
class Phone:
def __init__(self, make, storage, megapixels):
self.make = make
self.storage = storage
self.megapixels = megapixels
No Data Restrictions
A traditional class in Python does not provide any restrictions to accessing
data because everything is public by default. That means any instance of
the Phone class can change its attributes. Adjust your code to look like this:
my_phone = Phone("iPhone", 256, 12)
print(my_phone.storage)
my_phone.storage = 64
print(my_phone.storage)
challenge
class Phone:
def __init__(self, model, storage, megapixels):
self._model = model
self._storage = storage
self._megapixels = megapixels
The code above has a single underscore before each of the instance
variables, which means programmers will treat them as private. Add the
following code to the Phone class and click the TRY IT button.
class Phone:
def __init__(self, model, storage, megapixels):
self._model = model
self._storage = storage
self._megapixels = megapixels
The __dict__ attribute is found in every object in Python. Its job is to stores
all of the attributes in a class. You should see the following output:
These are all of the attributes in the Phone class as well as their values.
challenge
Solution
class Phone:
def __init__(self, model, storage, megapixels, carrier):
self._model = model
self._storage = storage
self._megapixels = megapixels
self._carrier = carrier
class PrivateClass:
def __init__(self):
self._private_attribute = "I am a private attribute"
obj = PrivateClass()
print(obj._private_attribute)
If _private_attribute really were private, Python would throw an error
message. Instead, Python sees _private_attribute as being public and
prints its value. Python does not have truly private attributes and
methods, though Python can approximate this behavior.
challenge
Solution
class PrivateClass:
def __init__(self):
self._private_attribute = "I am a private attribute"
def _private_method(self):
return "I am a private method"
obj = PrivateClass()
print(obj._private_method())
Double Underscore
Private Attributes
When you have a single underscore, the Python interpreter does not do
anything. It is just a convention. Using two underscores, however, causes
the Python interpreter to enforce changes. The specifics of the changes
will be discussed below, but Python gives you an approximation of private
attributes when using double underscores. We are going to use the same
code from the previous page, and add a second underscore before the
attribute private_attribute.
class PrivateClass:
def __init__(self):
self.__private_attribute = "I am a private attribute"
obj = PrivateClass()
print(obj.__private_attribute)
You should see an error message about PrivateClass not having the
attribute __private_attribute. Python does not allow you to access
__private_attribute from outside the class. Instead, let’s add a helper
method to the class that will return __private_attribute for us.
class PrivateClass:
def __init__(self):
self.__private_attribute = "I am a private attribute"
def helper_method(self):
return self.__private_attribute
obj = PrivateClass()
print(obj.helper_method())
Private Methods
You can also use the double underscores to restrict access to methods.
class PrivateClass:
def __init__(self):
self.__private_attribute = "I am a private attribute"
def __private_method(self):
return "I am a private method"
obj = PrivateClass()
print(obj.__private_method())
You should get an error message. Notice, however, that Python gives an
attribute error. It says that PrivateClass does not have the attribute
__private_method even though it was defined as a method.
challenge
Solution
class PrivateClass:
def __init__(self):
self.__private_attribute = "I am a private attribute"
def __private_method(self):
return "I am a private method"
def helper_method(self):
return self.__private_method()
obj = PrivateClass()
print(obj.helper_method())
Are Double Underscores Really Private?
No. Double underscores were not added to the Python language to
promote encapsulation. Rather, the double underscore is used to avoid
name collisions in inheritance. Enter the following code into the IDE and
click the TRY IT button.
class PrivateClass:
def __init__(self):
self.__private_attribute = "I am a private attribute"
obj = PrivateClass()
print(obj._PrivateClass__private_attribute)