Summary: In this tutorial, you will learn what is the significance of single and double underscores in Python i.e. _ and __, how they differ from each other, and when you should use them in our Python program.

In Python, an underscore (_) has a number of different uses. Let see each use one by one.

1. Variable Name

An underscore can be used as a name for a variable, for example:

_count = 10
print(_count)

2. Single Trailing Underscore

A single trailing underscore (_) is used to avoid naming conflicts with Python keywords. For example:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def to_string_(self):
        return f'Person(name={self.name}, age={self.age})'

p = Person('John', 35)
print(p.to_string_())

Output:

Person(name='John', age=35)

In this example, the method to_string_() uses a trailing underscore to avoid naming conflict with the Python str() function.

3. Single Leading Underscore

A name with leading underscore (e.g., _private) is used to indicate a “private” instance variable in a class. This is a convention only, and the Python interpreter does not enforce any kind of access control based on this naming convention.

class Person:
    def __init__(self, name, age):
        self._private = 'This is a private instance variable'
        self.name = name
        self.age = age

p = Person('John', 35)
print(p._private)

Output:

This is a private instance variable

Note that this is just a naming convention. It is simply a way to indicate to other programmers that the instance variable is meant to be treated as a non-public part of the class’s implementation.

4. Double Leading Underscore

A name with double leading underscores (e.g., __hidden) is used to implement “name mangling” in Python.

Name mangling is a technique used to make instance variables in a class more difficult to accidentally override in subclasses.

For example:

class Person:
    def __init__(self, name, age):
        self.__hidden = 'This is a hidden instance variable'
        self.name = name
        self.age = age

class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)
        self.student_id = student_id

s = Student('Alice', 20, '12345')
print(s.__hidden)

Output:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__hidden'

In this example, the __hidden instance variable is defined in the Person class. When we try to access this variable from the subclass Student, the attribute appears to be missing.

This is because Python applies “name mangling” to the variable name by adding a underscore prefixed class name to the variable. The actual name of the variable is now _Person__hidden.

Name mangling is not intended to provide real privacy for instance variables. It is simply a naming convention to avoid accidental name clashes between instance variables in a class hierarchy.

If you really want to protect the instance variables from being accessed or modified, you should use object-oriented techniques such as encapsulation and accessor methods.

5. Double Leading and Trailing Underscores

Double leading and trailing underscores (e.g., __special__) are used to denote special variables or methods in Python. These names are reserved by the Python interpreter and should not be used for user-defined variables or methods.

For example:

class MyClass:
    def __init__(self):
        self.__hidden = 'This is a hidden instance variable'
        self._private = 'This is a private instance variable'
        self.__special__ = 'This is a special instance variable'

mc = MyClass()
print(mc.__hidden)
print(mc._private)
print(mc.__special__)

Output:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute '__hidden'

In this example, the __hidden and __special__ instance variables are not accessible directly because they are affected by name mangling and are reserved by the Python interpreter, respectively.

The _private instance variable is accessible, but it is simply a naming convention to indicate that it is intended to be treated as a non-public part of the class’s implementation.

6. Underscores in Numeric Literals

An underscore can be used to separate digits in numeric literals for improved readability. For example:

x = 1_000_000
print(x)  # output: 1000000

These are some of the examples of the significances of single or double underscores in Python programming language.

Adarsh Kumar

I am an engineer by education and writer by passion. I started this blog to share my little programming wisdom with other programmers out there. Hope it helps you.

Leave a Reply