๐Ÿถ
Python

Python Single and Double Underscores Explained

By Filip on 10/05/2024

Learn how single and double underscores in Python affect object visibility, name mangling, and their use in avoiding naming conflicts.

Python Single and Double Underscores Explained

Table of Contents

Introduction

In Python, underscores are more than just decoration. Their position within a name gives them special meanings. Let's explore the different ways underscores influence variable and method behavior.

Step-by-Step Guide

In Python, underscores aren't just for visual appeal. They carry special meanings depending on where they appear in a name. Let's break down the different scenarios:

1. Single Leading Underscore (_var)

This is like a subtle hint to other programmers. It signals that the variable or method is intended for internal use within the current module or class. It's not enforced, but it's a good practice for readability and maintainability.

def _private_function():
    print("This is a private function.")

2. Single Trailing Underscore (var_)

This is used to avoid naming conflicts with Python keywords. For example, if you want to name a variable "class", you can use "class_" instead.

class_ = "This is a class"

3. Double Leading Underscore (__var)

This triggers name mangling. Python changes the name of the variable or method to make it harder to accidentally access from outside the class. This is useful for preventing name collisions in subclasses.

class MyClass:
    def __init__(self):
        self.__private_var = "This is a private variable."

4. Double Leading and Trailing Underscores (__var__)

These are special methods or attributes in Python, often called "dunder" methods. They have specific meanings and are used for operator overloading, object representation, and more.

class MyClass:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return f"MyClass object with value: {self.value}"

5. Single Underscore (_)

This is often used as a throwaway variable name when you don't need to use the value returned by a function.

for _ in range(5):
    print("Hello")

Remember, these are conventions, not strict rules. Python won't stop you from accessing "private" variables, but following these conventions makes your code more readable, maintainable, and less prone to errors.

Code Example

This Python code demonstrates the various roles of underscores in variable and method names. It covers single leading underscores for internal use, single trailing underscores to avoid keyword conflicts, double leading underscores for name mangling, double leading and trailing underscores for special methods, and single underscores as throwaway variables in loops. The code provides examples of each use case and explains their significance in Python conventions for code clarity and maintainability.

This script demonstrates the different uses of underscores in Python variable and method names.

class MyClass:
    """A class demonstrating underscore usage."""

    def __init__(self, value):
        """Initializes MyClass with a value and a private variable."""
        self.value = value
        self.__private_var = "This is a private variable."

    def _internal_method(self):
        """This method is intended for internal use only."""
        print("Inside _internal_method")

    def __str__(self):
        """Returns a string representation of the object."""
        return f"MyClass object with value: {self.value}"

    def public_method(self):
        """This method can be accessed from anywhere."""
        print("Inside public_method")
        self._internal_method()

# Single Leading Underscore
_internal_variable = "This is an internal variable."

# Single Trailing Underscore
class_ = "This is a string, not the keyword 'class'."

# Double Leading Underscore (Name Mangling)
my_object = MyClass(10)
# print(my_object.__private_var)  # This will raise an AttributeError

# Double Leading and Trailing Underscores (Dunder Methods)
print(my_object)  # Calls __str__ method

# Single Underscore (Throwaway Variable)
for _ in range(3):
    print("Looping...")

# Accessing methods
my_object.public_method()
# my_object._internal_method()  # Not recommended, but still accessible

This code showcases each underscore convention with clear examples and comments. Remember, while Python allows flexibility, adhering to these conventions enhances code clarity and maintainability.

Additional Notes

  • Importance of Conventions: While Python doesn't enforce strict rules about underscore usage, following these conventions is crucial for writing clean, maintainable code that other developers can easily understand.
  • Name Mangling and Inheritance: Name mangling with double leading underscores (__var) is particularly important when working with inheritance. It helps prevent accidental overriding of private attributes in subclasses, ensuring that changes in a parent class don't unintentionally break the behavior of its children.
  • "Private" is Relative: Remember that "private" in Python is a matter of convention, not strict enforcement. It's still possible to access attributes prefixed with double underscores (__var) from outside the class using name mangling rules, but doing so is highly discouraged.
  • Beyond Variables and Methods: Underscores are also used in other contexts in Python, such as in unpacking tuples and lists (e.g., x, _, z = (1, 2, 3) to ignore the second element) and in regular expressions to match any single character.
  • Readability Over Brevity: While underscores can make variable names more concise, prioritize readability. If a name becomes too cryptic or difficult to understand, it's better to use a more descriptive name, even if it's slightly longer.

By understanding the nuances of underscore usage in Python, you can write more expressive, maintainable, and Pythonic code.

Summary

Underscore Pattern Meaning Example
_var Internal use: Hints that the variable/method is for internal use within the module/class. _private_function()
var_ Avoid keyword conflicts: Prevents naming conflicts with Python keywords. class_ = "This is a class"
__var Name mangling: Makes it harder to accidentally access from outside the class. self.__private_var = "Secret"
__var__ Special methods/attributes: "Dunder" methods with specific meanings in Python. __init__, __str__
_ Throwaway variable: Used when you don't need the returned value. for _ in range(5):

Note: These are conventions for better code readability and maintainability, not strict rules.

Conclusion

In conclusion, while seemingly insignificant, underscores in Python are powerful tools for conveying meaning and intent within your code. From signaling internal use to enabling name mangling and facilitating special method interactions, understanding their various roles is essential for writing clear, maintainable, and Pythonic code. By adhering to these conventions, you enhance code readability and collaboration, making your programs more robust and easier to maintain. Remember, while Python offers flexibility, embracing these conventions elevates your code quality and professionalism.

References

Were You Able to Follow the Instructions?

๐Ÿ˜Love it!
๐Ÿ˜ŠYes
๐Ÿ˜Meh-gical
๐Ÿ˜žNo
๐ŸคฎClickbait