python logo

encapsulation in python


Python hosting: Host, run, and code Python in the cloud!

Encapsulation is a fundamental concept in object-oriented programming (OOP). In a nutshell, encapsulation in Python allows us to restrict the access to certain methods and variables within the class, ensuring that the data is hidden and safe from any unintentional modifications. Dive into this guide to understand encapsulation in Python with examples.

Boost Your Python Skills: Python Programming Bootcamp: Go from zero to hero.

Understanding Private Methods in Python

encapsulation. Restricted access to methods or variables

Consider the following scenario: We have a Car class, which consists of two main methods: drive() and the private method __updateSoftware(). When we instantiate the Car class, the __updateSoftware() method gets executed.

However, here’s the catch. You cannot invoke the private method (__updateSoftware()) directly using the object outside the class. Here’s how it’s done:

1
2
3
4
5
6
7
8
9
10
11
class Car:
def __init__(self):
self.__updateSoftware()
def drive(self):
print('driving')
def __updateSoftware(self):
print('updating software')

redcar = Car()
redcar.drive()
#redcar.__updateSoftware() # Error: This line is not accessible from the object.

Executing the above program would give you:

1
2
updating software
driving

The crux here is that encapsulation ensures accidental data access restrictions. Still, determined users can intentionally access it. Though the private methods appear hidden, they are simply renamed with the class name prefixed, like _Car__updateSoftware(). Therefore, you can still access the method using redcar._Car__updateSoftware().

Leveraging Private Variables in Python

Class with private variables

Just like methods, variables can be set as private. The beauty of private variables lies in their restricted access, ensuring they are modified only within the class methods, not outside. This is crucial for protecting vital application data.

Here’s an illustration:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Car:
__maxspeed = 0
__name = ""
def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"
def drive(self):
print('driving. maxspeed ' + str(self.__maxspeed))

redcar = Car()
redcar.drive()
redcar.__maxspeed = 10 # This won't alter the variable as it's private.
redcar.drive()

Now, what if you wish to modify a private variable? Use a setter method—a dedicated method designed to set or alter the value of private variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Car:
__maxspeed = 0
__name = ""
def __init__(self):
self.__maxspeed = 200
self.__name = "Supercar"
def drive(self):
print('driving. maxspeed ' + str(self.__maxspeed))
def setMaxSpeed(self, speed):
self.__maxspeed = speed

redcar = Car()
redcar.drive()
redcar.setMaxSpeed(320)
redcar.drive()

Setter methods are handy. While some private variables might need occasional updates, others might not necessitate any changes.

Encapsulation in Python: A Summary

In Python, encapsulation can be primarily categorized as:

  • Public Methods: These are accessible universally.
  • Private Methods: Exclusive to their class, these begin with two underscores.
  • Public Variables: These are universally accessible.
  • Private Variables: Restricted to their class or through specific methods (if provided), these also commence with two underscores.

Unlike some other programming languages, Python doesn’t support protected class methods. By encapsulating data, you get superior control over how much coupling exists in your code. Essentially, it permits a class to evolve its implementation without impacting other code segments.

Get Hands-on with Exercises

← Previous Topic | Next Topic →






Leave a Reply:




Tomislav Sat, 20 Jun 2015

"If you want to change the value of a private value, an setter method is used. This is simply a method that sets the value of a private value."

there is a typo --> change the value of a private value --> change the value of a private variable

Frank Sat, 20 Jun 2015

Thanks Tomislav! I updated it

Naveen Kerati Tue, 30 Jun 2015

so __ before a method or variable is considered as a private members is it...?

Frank Tue, 30 Jun 2015

Yes, if you put __ before a method or variable it is a private member. This means you can only access it using a method.

Crysis Sat, 25 Jul 2015

It's weird that for python the default access for a variable is public...

Frank Sat, 25 Jul 2015

Hi! It's cultural, in both Python and Java nothing prevents you from declaring all variables public, encapsulation is not strictly enforced in either language. In Java variables are private by default, in Python private variables are not enforced. In practice there is not a lot of difference because the developer has the authority on the code.

Terry Sat, 01 Aug 2015

And in C++ a struct is a class where all the members are public by default.

Terry Sat, 01 Aug 2015

Does Python support namespaces?

Frank Sat, 01 Aug 2015

Hi Terry,

Yes there are namespaces, but there are a variety of ways to implement them.
I would recommend the third method because it's the most clean solution.

Method 1: Use dictionary
Everything is an object in Python, a dictionary can act as a namespace.

#!/usr/bin/env python

class Person:
def sayHi(self):
print('Hi')

person = Person()

def python():
print('Python')

a_namespace = {'person':person, 'python': python}
a_namespace['person'].sayHi()
a_namespace['python']()

Method 2: Use packages
Create a directory /example/demo/ for your package. Inside it create a file called __init__.py with this contents:

#!/usr/bin/env python

def hello():
print('Hello world')


Then on the /example/ directory create a file test.py with this contents:

import demo

demo.hello()



Method 3: Use pkgutil
If you use pkgutil, you can create nested packages. Create a directory using this structure

<ul>
<li>/example/hello/</li>
<li>/example/hello/__init__.py</li>
<li>/example/hello/english/</li>
<li>/example/hello/english/__init__.py</li>
<li>/example/hello/dutch/</li>
<li>/example/hello/dutch/__init__.py</li>
<li>/example/test.py</li>
</ul>

In /example/hello/__init__.py put:

import pkgutil

__path__ = pkgutil.extend_path(__path__, __name__)
__path__.reverse()


In /example/hello/english/__init__.py put:
def hello():
print('Hello')


In /example/hello/dutch/__init__.py put:
def hello():
print('Hallo')


Your package is now complete. You can use nested namespaces.
Add this to /example/test.py and execute it:

import hello.english
import hello.dutch

hello.english.hello()
hello.dutch.hello()

Sajan Bhagat Fri, 07 Aug 2015

first of all __maxspeed is private but i'm still able to access it with object name & another thing when i used print(redcar.__maxspeed) it prints updated value 10 could you please explain the behaviour

Amit Thu, 24 Sep 2015

class Person:
__name #variable

class Programmer(Person)
self_Person__name ------> meaning full explanation please for this

Frank Thu, 24 Sep 2015

Hi Amit,
The class Programmer inherits from the class Person. The Person class has a variable called name. Because Programmer inherits from Person, it has access to the name variable. For more on inheritance, read here.

Jacky Wed, 16 Dec 2015

Hi,Frank
What's the text font in the source code?

Frank Sat, 19 Dec 2015

Hi Jacky, I think it's monospace

Sadia Sat, 20 Feb 2016

Hi Frank,
i am getting problem in file handling. i have written program which count number of lines and total words in file but it is not giving me correctly the number of words. my txt file is :

this is a text file. i have to count its lines and words.
this is a text file. i have to count its lines and words.


this program is giving me 58 words while there are not 58 words. Secondly when i write filename.read instead of filename.readlines then it does not give me correct number of lines. why?

count=0
filename=open("mfile.txt",'r')
handle=filename.readlines()
#print(handle)
for line in handle:
count+=1
print(count)

count_word=0
for word in line:
count_word=count_word+1
print(count_word)
Frank Thu, 25 Feb 2016

If you print word inside the for word loop, it will show it splits the line into single characters. To split into words use this:

count=0
filename=open("mfile.txt",'r')
handle=filename.readlines()
#print(handle)
for line in handle:
count+=1

print(count)

count_word=0
words = line.split(' ')
for word in words:
print word
count_word=count_word+1
print(count_word)

read() and readlines() are different methods. read() takes x characters from a file. readlines() reads the whole file and splits by newlines.

Sadia Sat, 27 Feb 2016

Many thanks :)

Amine Brikci-Nigassa Sun, 16 Apr 2017

"The private method __updateSoftware() can only be called within the class itself. It can never be called from outside the class."
Why don't you tell that the method can actually be called using redcar._Car__updateSoftware() ?
The "private" attributes and methods are not really hidden, they're just automatically renamed adding "_Car" in the beginning of their name... This truly prevents from accessing them *accidentally* but not intentionally...

Frank Sun, 16 Apr 2017

Thanks! I updated the post.