Understanding Leading Underscores (_) in Python: Convention, Not Enforcement

Understanding Leading Underscores (_) in Python: Convention, Not Enforcement

How Python signals internal APIs without enforcing access control

When i read production-grade Python code, I saw functions like _make_tracer, _serialize_locals, or _get_error_line. At first glance, the leading underscore looks just random programmer's way of writing code. But i was wrong.

In Python, a name that starts with an underscore is a hint for developers. It shows how the code is meant to be used. It usually means that something is internal and not meant to be used from outside. This becomes important in bigger programs where we separate what is public from what is private.


> The Idea

A leading underscore in Python:

marks a name as internal to a module or class and not intended for external use

Example:

def _make_tracer():
    pass        

This function is not meant to be imported or used outside its defining module.


> Convention, Not Enforcement

Unlike languages such as Java or C++, Python does not enforce access control.

You can still do:

from engine import _make_tracer        

and it will work.

Instead of restrictions, Python relies on developer discipline and clear conventions.


> Why This Matters

In small scripts, this may seem unnecessary. In real systems, it becomes critical.

Consider a module:

def trace_code():
    ...

def _make_tracer():
    ...

def _serialize_locals():
    ...        

Here let's assume trace_code is a public API while _make_tracer, _serialize_locals are internal helpers

This separation ensures:

  1. external users interact only with stable interfaces
  2. internal logic can evolve without breaking dependencies


> Practical Benefits

1. Clear API Boundaries

Without underscores, everything looks public:

make_tracer()
serialize_locals()
get_error_line()        

This can create ambiguity, But with underscores:

_make_tracer()
_serialize_locals()
_get_error_line()        

The boundary becomes explicit.

2. Safer Refactoring

Internal functions can be changed freely:

  1. renamed
  2. removed
  3. rewritten

Because external code is not supposed to depend on them.

3. Cleaner Imports

Python’s import behavior respects this convention:

from module import *        

will exclude names starting with _

This prevents accidental exposure of internal logic.


> Variations of Underscore Usage

Understanding _name also requires distinguishing it from other underscore patterns.


1. Single Leading Underscore: _name

  1. signals internal use
  2. purely a convention


2. Double Leading Underscore: __name

Used inside classes:

class A:
    def __method(self):
        pass        

This triggers name mangling, making it harder (not impossible) to access externally.


3. Double Underscore on Both Sides: name

Special methods:

__init__
__str__
__repr__        

These are part of Python’s data model, not conventions.


4. Single Underscore Alone: _

Used as:

  1. throwaway variable
  2. REPL last result


> When You Should Use _

Use a leading underscore when:

  1. a function is not part of the public API
  2. it is tightly coupled to internal logic
  3. it may change without notice


> When You Should NOT Use _

Avoid it when:

  1. the function is meant for reuse
  2. it forms part of your module’s contract
  3. external users are expected to call it


> Final Takeaway

A leading underscore in Python is a small detail with significant impact.

It does not enforce privacy, but it enforces discipline.

When used correctly, it:

  1. clarifies intent
  2. separates public and internal code
  3. improves maintainability


> One-Line Summary

_name in Python means “this is internal — use it at your own risk.”


To view or add a comment, sign in

More articles by Mohit Kumar

  • Serialization & Deserialization for Backend Engineers

    >>> Why This Topic Actually Matters If you strip backend engineering to its core, everything revolves around data…

  • Backend Routing

    If you are building any web application, routing is one of the most important concepts you must understand. Whether you…

  • HTTPS (REQUEST RESPONSE CYCLE)

    The Complete HTTP & Networking Playbook for Developers Targeting high paying Backend Job >>> Statelessness: The…

Explore content categories