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

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 name | Style | Examples |
|---|---|---|
| Module | short, lowercase, underscores if they help | csv_tools, parser |
| Package | short, lowercase, underscores discouraged | billing |
| Class | CapWords | InvoiceLine, HTTPServerError |
| Exception | CapWords, ending in Error for errors | ParseError |
| Type variable | CapWords, preferably short | T, AnyStr, KT_contra |
| Function, method, variable | lowercase with underscores | total_due, parse_line() |
| Constant | capitals with underscores | MAX_RETRIES, TOTAL |
| First argument | self for instance methods, cls for class methods | def 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.
_single_leading: a "weak internal use" indicator. It tells other developers not to rely on the name, andfrom module import *skips names that start with an underscore. Nothing else prevents access.single_trailing_: avoids a clash with a keyword, as inclass_ortype_. PEP 8 prefers this to misspellings likeclss, and suggests that a synonym may be better still.__double_leading: inside a class, triggers name mangling. The attribute__balancein classAccountis stored as_Account__balance.__double_both__: special names that Python itself defines, such as__init__,__len__or__file__. PEP 8 is firm: never invent such names; only use them as documented.
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:
- pep8-naming adds N8xx codes to flake8, for example N802 for a function name that is not lowercase.
- ruff reimplements those rules under the same N codes; select them with
--select Nor in its configuration. - pylint reports
invalid-name(C0103), with a configurable pattern for each kind of name.
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
- PEP 8, "Naming Conventions" and "Public and Internal Interfaces".
- Python Tutorial, "Private Variables" (name mangling).
- pycodestyle documentation (scope: naming conventions supported through plugins); pep8-naming README; pylint documentation, message
invalid-name; ruff rules reference, pep8-naming (N). Tool output above produced with ruff 0.16 and pylint 4.1.
PEP 8, section by sectionPEP 8, explained section by section
What the official Python style guide actually says, section by section, which parts tools can check, and where it tells you to use your judgment.
Readable code in practiceReadable code, beyond PEP 8
Code can pass every linter and still be hard to follow. Names, flat control flow, small functions and idioms that say what they mean, with a before-and-after.
Linters & formattersflake8 and pylint compared
Same file, two linters: flake8 found nothing, pylint found six things. What each tool checks, how to configure it and when to use both.