Private Methods And Functions In Python With Access Modifiers

Christopher Franklin
Weekly Python
Published in
3 min readJan 7, 2021
Photo by Markus Spiske on Unsplash

When working with object-oriented programming languages we sometimes need to keep a piece of code from being executed arbitrarily from anywhere else in the system. To solve this problem, the concept of access modifiers were introduced into early language design.

In languages like C++, Java, or C# we can use the reserved keywords public, protected, or private to mark the members of a class. Python does have all three access modifiers, but it doesn’t use keywords to mark a member. Instead, Python uses underscores _ to mark a function or variable as protected or private.

However, Python does not actually enforce these access modifiers like other languages. Instead, it uses name mangling to obfuscate the function or variable and make it harder to find. In other words, if you really wanted to access it, you could. The only thing forcing this convention is you as the programmer.

Protecting Module Functions

When working with module wide functions, sometimes we don’t want our function to be usable to anyone that imports the module. One way to accomplish that is to put one or two underscores in front of the function name.

For example, if we define a module file random_module.py :

def public_func():
print("This function can be seen")

def __hidden_func():
print("You can't see this during import")

We can then import that module in the interpreter and try to use it:

>>> import random_module>>> random_module.public_func()
This function can be seen
>>> random_module.__hidden_func()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: module 'random_module' has no attribute '__hidden_func'

This also works if we use from random_module import * so our private function can stay that way.

Class Private Methods and Variables

Sometimes we want to put restrictions on our class members where they can’t be accessed outside the class or even from any subclasses. In those cases, we can declare a variable or method as private using the __ double underscore.

class Example:
def __init__(self):
self.__a = "This is a private variable"
def __can_not_run(self):
print("Can't be executed outside of this class")

If we instantiate this class and attempt to access the variable or method:

>>> ex = Example()>>> print(ex.__a)
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Example' object has no attribute '__a'
>>> ex.__can_not_run()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Example' object has no attribute '__can_not_run'

We can see that neither attribute is available for us to use. But can we access them if we subclass?

class SubExample(Example):
def print_a(self):
print(self.__a)

Now if we import this:

>>> sub = SubExample()>>> sub.print_a()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'SubExample' object has no attribute '_SubExample__a'

The error looks slightly different but it is still an error! As I mentioned above, Python internally uses name mangling to actually hide the attributes. If a variable is protected, instead of private, it will be moved into a reference _CLASS_VARIABLE to make it less accessible. But if you know that pattern, you can actually reach in and use any protected variable from anywhere.

Class Protected Methods and Variables

Ok, so we saw in the last example that if the variable or method is only protected we should be able to access them from a subclass. So, how do we define a protected attribute? The answer is to use a _ single underscore in front of the name.

class ProtectedExample:
def __init__(self):
self._b = "Available from subclass"

Now we can create a subclass and check it out!

class SubProtected(ProtectedExample):
def print_b(self):
print(self._b)

And if we load this into the interpreter:

>>> pe = ProtectedExample()>>> print(pe._b)
Traceback...
>>> sp = SubProtected()>>> sp.print_b()
Available from subclass

And with that, you now know how to encapsulate and obfuscate your functions and variables inside Python using Access Modifiers.

P.S. If you are looking for challenging applications to build in Python, don’t forget to sign up for our free weekly challenge newsletter here!

--

--