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.