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.