2022-07-10

Underscore Positions in Python

Introduction

In Python, the underscore (_) character holds a significant position as it's often used in various contexts, each with a different meaning. This article will walk you through the different use-cases of underscores in Python.

Underscore Only (_)

In Python, a single, stand-alone underscore (_) is frequently used as a variable in programming. It's often referred to as a 'throwaway' variable because its main purpose is to hold values that will not be used again. While the name may seem dismissive, it plays a crucial role in writing clean, efficient Python code.

Here are some instances where you might see or use the underscore as a throwaway variable:

Ignoring a Value

When unpacking values, you may occasionally encounter values that you don't need. Instead of creating a useless variable that will only clutter your namespace, you can assign the unwanted value to an underscore.

python
a, _, c = (1, 2, 3 )
print(a, c) # Outputs: 1 3

In this example, the tuple (1, 2, 3) is being unpacked into a, _, and c. The second value isn't needed, so it's assigned to the underscore.

Looping a Specific Number of Times

In loops, the underscore is often used when the loop variable itself isn't used within the loop. This is especially common in loops that are used to repeat a block of code a specific number of times.

python
for _ in range(3):
    print("Hello, World!") # Outputs "Hello, World!" three times

Here, the loop is merely printing "Hello, World!" three times. The actual loop variable is irrelevant, so an underscore is used.

Working with Interactive Interpreter

In the Python interactive interpreter, the underscore variable is automatically assigned the result of the last operation. This can be handy when working in the Python shell or Jupyter notebooks.

python
>>> 10 + 20
30
>>> _
30

In this example, the sum of 10 and 20 is 30. When _ is entered, it retrieves the last operation's result.

Single Underscore as Prefix (_var)

In Python, a variable, function, or method that starts with a single underscore is a clear signal to other programmers that the element is intended for internal use. It doesn't restrict access as 'private' would in languages like Java or C++, but serves as a gentle nudge to discourage direct access.

Variables and Methods in a Class

When a single underscore is used as a prefix to a variable or method in a class, it's a convention that these elements are meant for internal use within the class. They can, however, still be accessed and modified in the outside world.

Here's an example of how this might look in practice:

python
class MySecretClass:
    def __init__(self):
        self._secret_attribute = 42

    def _secret_method(self):
        print("This is an internal method!")

In this example, _secret_attribute and _secret_method are intended for internal use within the MySecretClass class. But Python does not enforce any restrictions, and these elements can still be accessed from an object of the class.

python
obj = MySecretClass()
print(obj._secret_attribute)  # Outputs: 42
obj._secret_method()  # Outputs: "This is an internal method!"

Functions

Just like with class attributes and methods, a single underscore at the beginning of a function name indicates that the function is for internal use. This typically means that the function is not part of the public API of a module, and thus, should not be accessed directly.

python
def _internal_function():
    print("This function is for internal use.")

In this example, _internal_function is a function that is intended to be used internally, within the module where it is defined. As with class attributes and methods, Python does not enforce this, and the function can still be called as usual.

Single Underscore as Suffix (var_)

In Python, you might sometimes find a variable, function, or method name with a trailing underscore (e.g., var_). This is less common than some of the other underscore patterns, but it serves an important purpose: it allows you to use Python keywords as variable names.

Python has a set of reserved keywords that cannot be used as variable names because they have special meanings in the language's syntax. These include words like class, def, for, if, and while, among others.

However, sometimes it might be useful to use a Python keyword as a variable name because it clearly and accurately represents what the variable is meant to hold. In such cases, you can add a trailing underscore to the keyword to use it as a variable name.

Here's an example:

python
# This would cause a syntax error:
# class = 'Computer Science 101'

# But this is perfectly valid:
class_ = 'Computer Science 101'

In this example, class_ is used as a variable name to hold a string representing a class name. class would have been the most intuitive variable name to use, but since it's a reserved keyword in Python, it cannot be used as a variable name. So, class_ is used instead.

Remember, the use of a trailing underscore to avoid naming conflicts with Python keywords is merely a convention, not a rule enforced by the Python language. Like many conventions in Python, it's designed to enhance code readability and maintainability.

It's also important to note that while this convention allows you to avoid conflicts with Python keywords, it doesn't help with conflicts with built-in function names. For example, list_ = [1, 2, 3] is valid Python code, but it might be confusing because list is a built-in Python function. In general, it's best to avoid names that could be confused with built-in functions or types, even if you're using a trailing underscore.

Two Underscores as Prefix (__var)

In Python, if a variable, function, or method starts with two underscores (__var), it triggers a mechanism called name mangling. This is different from single underscore prefix (_var). Name mangling is a way Python alters the variable name to make it harder to create subclasses that accidentally override the private methods and attributes.

Let's dive deeper into the concept of name mangling and how it is used in Python.

Name Mangling

Name mangling is a mechanism that changes the name of the variable in a way that makes it harder to fetch or alter by mistake. It's a way to ensure the "privacy" of the variable or method, even though Python doesn't support the concept of fully private variables or methods.

When a variable or method starts with two underscores, Python alters its name to include the class name as a prefix, which makes it less likely to be accessed or modified accidentally.

Here's an example:

python
class MyClass:
    def __init__(self):
        self.__private_var = "I am private"

The variable __private_var is subject to name mangling, which makes it appear different outside the class.

python
obj = MyClass()
print(obj.__private_var)  # Outputs: AttributeError: 'MyClass' object has no attribute '__private_var'

Notes on Name Mangling

While name mangling can provide a degree of privacy, it's not foolproof. The mangled name can still be accessed directly if you know the syntax. Here's how you can access the "private" variable from the previous example:

python
print(obj._MyClass__private_var)  # Outputs: "I am private"

As you can see, Python has added _MyClass (an underscore followed by the class name) before __private_var.

It's also worth noting that name mangling doesn't occur if there are two underscores at both the beginning and the end of the variable or method name (e.g., __var__). This pattern is used for special methods, often referred to as "dunder" methods.

Two Underscores as Both Prefix and Suffix (__var__)

Python methods that are surrounded by double underscores at the beginning and end (__var__) are known as "dunder" methods (short for "double underscore"). These methods have a special significance and are not subjected to name mangling. They are also known as "magic methods" due to their special properties.

These dunder methods are used to implement specific behaviors in Python, usually mimicking built-in types. Some of the most commonly used dunder methods include __init__, __str__, __len__, and __getitem__.

Underscore as Infix (var_var)

Underscores are used within names to improve readability, especially with multi-word variable, function, or method names. This is called snake case, and it's commonly used in Python.

python
def calculate_average_score():
    ...

In this function, the underscore separates the words calculate, average, and score making it easier to read.

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!