PEP 8, section by section

Python Naming Conventions: Modules, Classes, Functions, Constants and Underscores

PEP 8, section by section · · Published 2026-10-27

Two green street name signs, SE Nye Av and SE 3rd Dr, mounted on a pole above the back of a stop sign under a grey sky
Street name signs at the corner of SE Nye Avenue and SE 3rd Drive, 2024. Photo: Roc0ast3r, CC0.

Names are the part of style that tools can check least and readers notice most. PEP 8 gives a clear scheme for how names should look, so that a reader can tell a class from a function or a constant at a glance. Choosing what a name says is still up to you.

The overriding principle

Before any rule, PEP 8 states one principle: names that are visible to users as part of a public API "should follow conventions that reflect usage rather than implementation". A function that callers use like a class can be named like one; an attribute that behaves like data should look like data even if a property computes it. The guide also admits that "the naming conventions of Python's library are a bit of a mess", so you will meet exceptions in the standard library itself, such as mixedCase methods in the logging and unittest modules, kept for backwards compatibility.

The styles, and where each one goes

Kind of nameStyleExamples
Moduleshort, lowercase, underscores if they helpcsv_tools, parser
Packageshort, lowercase, underscores discouragedbilling
ClassCapWordsInvoiceLine, HTTPServerError
ExceptionCapWords, ending in Error for errorsParseError
Type variableCapWords, preferably shortT, AnyStr, KT_contra
Function, method, variablelowercase with underscorestotal_due, parse_line()
Constantcapitals with underscoresMAX_RETRIES, TOTAL
First argumentself for instance methods, cls for class methodsdef from_row(cls, row)

Two details are easy to miss. In CapWords, acronyms are written in capitals: PEP 8 prefers HTTPServerError to HttpServerError. And mixedCase (initial lowercase letter, then capitals) is allowed only "in contexts where that's already the prevailing style", to keep backwards compatibility; new Python code should not introduce it.

Constants are a convention, not a language feature: nothing stops code from reassigning MAX_RETRIES. The capitals tell readers not to, and type checkers can enforce it if you annotate the name with typing.Final.

What underscores mean

Leading and trailing underscores carry meaning in Python, some of it enforced by the language.

Name mangling is easy to see in practice:

class Account:
    def __init__(self):
        self.__balance = 0
        self._currency = "EUR"


acct = Account()
print(acct._currency)
print(acct._Account__balance)
try:
    acct.__balance
except AttributeError as exc:
    print(type(exc).__name__)
print(sorted(n for n in vars(acct)))
EUR
0
AttributeError
['_Account__balance', '_currency']

Mangling is not privacy: the attribute is still reachable under its mangled name. Its purpose, according to PEP 8, is to avoid accidental name clashes with attributes of subclasses, and the guide notes that "not everyone likes name mangling". For ordinary non-public attributes, a single underscore is the usual choice.

Public and internal interfaces

PEP 8 ties naming to the question of what is public. Documented interfaces are public; everything undocumented should be assumed internal. Modules should declare their public names in __all__, and internal names should still carry a leading underscore even when __all__ is set. When in doubt, PEP 8 recommends making an attribute non-public, because it is easier to make it public later than the reverse.

Names to avoid

PEP 8 asks you never to use the letters l (lowercase el), O (uppercase oh) or I (uppercase eye) as single-character variable names, because in some fonts they look like the digits one and zero. pycodestyle enforces this with E741 for variables, E742 for classes and E743 for functions. Beyond that, the guide says little about meaning, but the principle of naming for usage leads to familiar advice: name a function after what it returns or does (parse_date, not process), name booleans as statements (is_valid, has_children), and keep one-letter names for short loops and mathematical code where the convention is obvious.

Which tools check names

pycodestyle deliberately leaves naming out, apart from E741 to E743; its documentation points to the pep8-naming plugin for flake8. Other tools do check names:

The tools do not always agree. Given a module containing myVar = 1 and a function DoThing, ruff reported N816 (mixedCase variable in global scope) and N802, while pylint reported C0103 for both, describing myVar as a constant that should be UPPER_CASE, because pylint treats module-level assignments as constants by default. Configure the one tool your project uses rather than trying to satisfy all of them. Our comparison of flake8 and pylint explains how their checks differ, and the guide to readable code returns to what makes a name good rather than merely well-formed.

Sources