If you have worked with languages like C#, JAVA or C++, you are familiar with the concept of private, protected and public fields. Although Python has great support for inheritance and polymorphism, the OO-concept encapsulation is not so well supported. What are your options?

How to create a private variable in Python?

In a language like C# you can make members public or private like this:

public ID = 0;
private _name = "Pipo";
protected _salary = 2000;

In Python, variables in classes are public by default. Can you make them private?

No!

Python does not know the concept of private variables. But you have a few options to mimic the behavior of a private variable.

1) Internal use with a single leading underscore

Variables and functions with a single leading underscore indicate internal use. What does that mean?

  1. a = 10 a is public
  2. _b = 20 _b is also public but is not imported when using the from . import * syntax
  3. _b = 20 The underscore shows the intent of a private variable (according to certain style conventions)

Example:

config.py:

a = 10
_b = 20

main.py:

from config import *

print(a)
print(_b)

Output:

10
NameError: name '_b' is not defined

A single leading underscore does not change the visibility (also known as accessibility) but it does prevent from being imported using the * syntax.

The single leading underscore just suggests private.

2) Name mangling with a double leading underscore

Attributes prefixed with a double underscore will be name-mangled. Name mangling is a technique to give members a unique name to prevent conflicts with subclasses that want to use the same name for different purposes.

The python interpreter will rename the attribute __name in class A to _A__name, which prevents you from accessing it accidentally.

Does name mangling enable encapsulation? No, because is does not restrict access to such members.

Code example:

class Employee:
def __get_name(self):
return "Pipo"

e = Employee()
print(e._Employee__get_name()) # accessible via name mangled attribute name
print(e.__get_name()) # attribute is name mangled and thus causes an error

Output:

Pipo
AttributeError: 'Employee' object has no attribute '__get_name'

Conclusion: private in Python is not possible

There is no way to make an attribute private in the sense of:

PEP8 describes the use of leading underscores for the purposes described above but makes no mention of private and public variables.

My Advice

I’ve seen and used both single and double leading underscores to indicate visibility of attributes and methods.

Use whatever standards apply in your project. The most important thing to remember is that _ and __ will not make variables truly private in Python but they can indicate the intent optically.

Written by Loek van den Ouweland on 2020-09-18.
Questions regarding this artice? You can send them to the address below.