What is the meaning of single and double underscore before an object name?

Learn what is the meaning of single and double underscore before an object name? with practical examples, diagrams, and best practices. Covers python, oop, naming-conventions development techniques...

Understanding Python's Naming Conventions: Single and Double Underscores

Hero image for What is the meaning of single and double underscore before an object name?

Explore the meaning and implications of single and double underscores before object names in Python, uncovering their roles in convention, name mangling, and private attributes.

In Python, the use of single and double underscores before an object's name (e.g., variable, method, attribute) carries specific meanings and implications, primarily related to naming conventions and access control. While Python doesn't enforce strict 'private' or 'protected' access modifiers like some other languages, these underscore prefixes serve as strong hints to developers and trigger specific behaviors within the language itself. Understanding these conventions is crucial for writing clean, maintainable, and idiomatic Python code.

Single Leading Underscore: _variable (Convention for Internal Use)

A single leading underscore _ before a name (e.g., _my_variable, _my_method) is a convention indicating that the name is intended for internal use within the module or class. It's a gentle warning to other developers that this attribute or method is not part of the public API and should not be accessed directly from outside the class or module. Python itself does not prevent access to these names; it's purely a convention. However, there's one specific behavior related to from module import * statements.

class MyClass:
    def __init__(self):
        self.public_attribute = "I am public"
        self._internal_attribute = "I am for internal use"

    def public_method(self):
        return "This is a public method"

    def _internal_method(self):
        return "This is an internal method"

# Accessing attributes and methods
obj = MyClass()
print(obj.public_attribute)       # Output: I am public
print(obj._internal_attribute)    # Output: I am for internal use (but don't do this externally!)
print(obj.public_method())        # Output: This is a public method
print(obj._internal_method())     # Output: This is an internal method (conventionally internal)

# Behavior with 'from module import *'
# If this were in a module, `_internal_attribute` and `_internal_method`
# would NOT be imported by `from module import *`.

Demonstration of single leading underscore convention.

Double Leading Underscore: __variable (Name Mangling)

A double leading underscore __ (e.g., __private_attribute, __private_method) triggers a mechanism called 'name mangling' in Python. When a name within a class definition starts with two underscores and does not end with two underscores (to avoid conflicts with special methods like __init__ or __str__), Python automatically renames it to _ClassName__variable. This mangling makes it harder, though not impossible, to access the attribute or method directly from outside the class, effectively providing a form of 'pseudo-private' access.

class MyClass:
    def __init__(self):
        self.public_data = "Public data"
        self.__private_data = "Secret data"

    def get_private_data(self):
        return self.__private_data

obj = MyClass()
print(obj.public_data)         # Output: Public data
# print(obj.__private_data)    # This would raise an AttributeError

# Accessing through name mangling (not recommended for general use)
print(obj._MyClass__private_data) # Output: Secret data

# Accessing via a public method
print(obj.get_private_data())  # Output: Secret data

Illustrating double leading underscore and name mangling.

classDiagram
    class MyClass {
        + public_data
        - __private_data
        + get_private_data()
    }

    MyClass --> _MyClass__private_data : mangled_access

Class diagram showing public and name-mangled 'private' attributes.

Summary of Underscore Conventions

The choice between using a single or double underscore depends on the intended visibility and purpose of the attribute or method. Single underscores are for internal use within a module or class, relying on convention. Double underscores invoke name mangling, primarily to prevent name clashes in inheritance and to strongly suggest that an attribute is private to the class.

flowchart TD
    A[Identifier Name] --> B{Starts with _?}
    B -- Yes --> C{Starts with __ and not ends with __?}
    B -- No --> D[Public Identifier]
    C -- Yes --> E[Name Mangling: _ClassName__identifier]
    C -- No --> F[Convention: Internal Use (_identifier)]
    E --> G[Pseudo-Private (Harder to access externally)]
    F --> H[Conventionally Private (Accessible, but discouraged)]

Decision flow for Python identifier underscore conventions.