Many Ways the Single (_) and Double (__) Underscore in Python is Used

Learn the different ways we can use single underscore(_) and double underscore(__) in Python.

Picture of Nsikak Imoh, author of Macsika Blog
A blank image with the text Many Ways the Single (_) and Double (__) Underscore in Python is Used
A blank image with the text Many Ways the Single (_) and Double (__) Underscore in Python is Used

It may come as a surprise to you that many Python developers do not know about the functionalities of underscore(_) and double underscore(__) in Python.

The underscore(_) and double underscore(__) is a unique character in Python that is useful in writing Python code productively.

In the article, you will learn the different ways we can use single underscore(_) and double underscore(__) in Python.

What are the Uses of the Single and Double Underscores in Python

Here are the different ways that the single underscore(_) and double underscore(__) are used in Python:

1. Store the value of the last expression in the Interpreter

The value of the last expression in the Python interpreter is automatically assigned and stored in the underscore (_) as a variable.

This makes it possible to easily pick up the value of the last variable from where you left it.

You can use the value stored in this variable for other operations, and expressions, and even assign this value to another variable when needed.

Example of using underscore to store the value of the last expression in the Interpreter

>>> 1 + 1
2
>>> _     # stores the result of the above expression
2
>>> _ + 3
4
>>> _
4
>>> a = _  # assigning the value of _ to another variable
>>> a
4

2. Ignore one or more values when unpacking

The Underscore(_) comes in handy when you want to ignore some specific values while unpacking.

This is mostly for values that are insignificant to the main processing of the program.

By assigning the values to a special variable underscore(_), we are declaring that a specific value or specific range of values should not be assigned to any variable.

When unpacking, a single underscore (_), is used to ignore one value while an asterisk before a single underscore (_) is used to ignore multiple values*.

The asterisk before a single underscore (*_) is called Extended Unpacking, only available in Python 3.x

Example of using underscore to ignore one or more values when unpacking

Ignore a single value

a, _, b = (1, 2, 3) # a = 1, b = 3
print(a, b)

Ignore multiple values

a, *_, b = 1, 2, 3, 4, 5, 6, 7
print(a, b)

3. Loop through Iterable

The underscore(_) can be used as a variable in looping through iterable.

Example of using underscore to iterate through a range of values in a for loop

for _ in range(15):
    print(_)

Example of using underscore to iterate over a list of values

languages = ["English", "German", "French", "Arabic"]
for _ in languages:
    print(_)

Example of using underscore to iterate with a while loop

_ = 15
while _ < 20:
    print(_, end = ' ')
    _ += 1

4. Separate Digits of Numbers

Sometimes, it might be confusing to adequately work with a large number without a separator.

You can use an underscore as a separator to separate the group of digits as you choose for better understanding.

**Example of using underscore to separate digits of numbers in Python **

billion = 1_000_000_000
population_of_china = 1_200_000_000
print(billion)
print(population_of_china)

You can also use an underscore(_) to separate the binary, octal, or hex parts of numbers.

Example

binary = 0b_0010
octa = 0o_64
hexa = 0x_23_ab

The best part, you can also check whether they are correct or not by converting them into integers using the “int” method

print(binary)
print(octa)
print(hexa)

5. Specify Internationalization(i18n) or Localization(l10n) functions

The underscore is conventionally used to signify internationalization or a section where translation may be required or can be added.

It is just a convention and does not have any syntactic functions.

The underscore does not mean i18n or l10n, and it is just a convention that binds the i18n or l10n to the underscore variable has been from C convention.

You can find this convention in used at the built-in library gettext which is for i18n or l10n.

Django which is a Python web framework that supports i18n or l10n also introduces and uses this convention.

Example of using underscore to specify Internationalization(i18n) or Localization(l10n) functions

import gettext
gettext.bindtextdomain('myapplication','/path/to/my/language/directory')
gettext.textdomain('myapplication')  
_ = gettext.gettext# ...print(_('This is a translatable string.'))

6. Give Special Meaning to Name of Variables and Functions

Single and double underscores have a meaning in Python variable and method names.

Some of that meaning is merely by convention and intended as a hint to the programmer, while some are enforced by the Python interpreter.

The underscore may be most used in assigning special names to variables and functions.

The PEP8 which is a Python convention guideline introduces the following 4 naming cases:

1. Single underscore as a leading character of variable names _var_name

The underscore as a prefix to a variable name is meant as a hint to another developer that a variable or method starting with a single underscore is intended for internal use.

This convention is defined in PEP 8.

**This convention is used for declaring private variables, functions, methods, and classes in a module.

However, this isn't enforced by Python. It is a “weak internal use indicator”.

The private names will not be available if import a module using from module import *, but they will be available if you import it directly using import module.

Python does not have strong distinctions between “private” and “public” variables like Java does.

It's like someone put up a tiny underscore warning sign that says:

Example of using a single underscore as a leading character of a variable name

_private_var = 'Private string'
_internal_version = 1.0

# private class  
class _Base: 
    _hidden_factor = 2 # private variable
    def __init__(self, price):  
        self._price = price
    
    def _double_price(self): # private method  
        return self._price * self._hidden_factor
        
    def get_double_price(self):  
        return self._double_price() 

2. Single underscore as a trailing character of variable names var_name_

Sometimes, for whatever reason, you may want to use Python Keywords as a variable, function, or class name.

This naming convention allows you to do that while avoiding conflict with Python keywords or built-ins.

All you need to do is add an underscore at the end of the name of the keyword you want to use.

Example of using a single underscore as a trailing character of a variable name

class_='ClassName' # Avoid conflict with 'class' keyword
str_ = type("String") # Avoid conflict with 'str' built-in type

3. Double underscores as a leading character of variable names __var_name

Double underscores as a leading character of variable names are used for the name mangling in Python.

Name Mangling occurs when the Python interpreter alters the variable name in a way that does not clash when the class is inherited.

The Double Leading Underscores tells the Python interpreter to rewrite the attribute name of subclasses to avoid naming conflicts.

Example of using double underscores as a leading character of variable names

class Car():
    def __init__(self):
        self.a = 1
        self._b = 2
        self.__c = 3
tesla = Car()
print(dir(tesla))

Output

['_Car__c',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_b',
 'a']

When we run the code above, all the attributes of the class object are returned.

There are some changes to be noted:

self.a variable appears in the list without any change.

self._b Variable appears in the list without any change.

self.__c variable does not appear alone in the list? If you carefully look at the list of attributes, you will find an attribute called _Car__c. This is what name mangling involves in Python. It is done to avoid overriding the variable in subclasses.

Why? You may ask.

Let's create another class that inherits the Car class to see how overriding works.

class Toyota(Car):

    def __init__(self):
        super().__init__()
        self.a = "overridden"
        self._b = "overridden"
        self.__c = "overridden"
        
toyota = Toyota()
print(toyota.a)
print(toyota._b)
print(toyota.__c)

Output

overridden
overridden

AttributeError: 'Toyota' object has no attribute '__c'

Here, the name mangling is at work again.

It changes the toyota.__c to _Toyota__c.

To get the element, it has to be accessed this way:

print(obj2._SecondClass__c)

Output

overridden

You can also access the previously created variable using _Car__c

print(obj1._Sample__c)

You can also use the Double Leading Underscores for the method names.

Example

class Car:
    def __info(self):
        return "everything"

def get_info(self):
    return self.__info()

car = Car()
print(car.get_info())
print(car.__info())    # we get an error here

4. Double underscores as a leading and trailing character of method names __var_name__

Names that have both leading and trailing double underscores are reserved for a special use in Python language.

These names are called dunder methods or often referred to as magic methods.

We do not recommend using names that start and end with double underscores (“dunders”) in your own programs

This helps you avoid code conflicts that may arise with future changes to the Python language.

This convention is used for special variables or methods such as __init__, __len__.

These methods provide special syntactic features or do special things.

For example, __file__ indicates the location of the Python file, and __eq__ is executed when the a == b expression is executed.
The special method 'init' is used for initializing a class

Wrap Off

We hope you have studied the different ways to use single underscore(_) and double underscore(__) in Python.

If you learned from this tutorial, or it helped you in any way, please consider sharing and subscribing to our newsletter.

Please share this post and for more insightful posts on business, technology, engineering, history, and marketing, subscribe to our newsletter.

Get the Complete Code of Python Code Snippets on Github.

Connect with me.

Need an engineer on your team to grease an idea, build a great product, grow a business or just sip tea and share a laugh?