Python underscore naming conventions

September 16, 2022

Overview

Underscores in Python convey information about the intended use of a variable, method, or function. This information is either accepted by convention or enforced by the interpreter.

Single Leading Underscore

  • conveys that an attribute is intended for internal use
  • the interpreter does not prevent access to the attribute, however, it does prevent wildcard imports for the attribute (unless the attribute is included in an __all__ list within the module)
_x = 123

Fails:

from module import *

Passes:

from module import _x

Single Trailing Underscore

  • avoids naming conflicts with Python keywords or other builtins and namespaces
x_ = 123

Double Leading Underscore

  • applies name mangling to class attributes (variables and methods)
    • protects the attribute from getting overridden in subclasses
  • direct access to the attribute is obfuscated
    • accessor methods can be created to operate on the instance value itself
class Example:
    def __init__(self):
        self.__x = "123"

Fails:

e = Example()
e.__x

Passes:

e = Example()
e._Example__x

Double Leading and Trailing Underscore

  • name mangling is not applied to class attributes
  • class method names are reserved for special use in the language and are known as dunder (double underscore) methods or magic methods
    • usage should generally be avoided to prevent conflicts with the language
class Example:
    def __init__(self):
        self.__x__ = "123"

Single Underscore

  • conveys that a variable is temporary or not important
    • useful when an enumeration or unpacked iterable value is not needed
for _ in range(123):
    print("Hello, World!")