Skip to content

Naming Convention

A variable can have a short name (like x and y) or a more descriptive name (like age, carname, total_volume). Rules for Python variables:

  • A variable name must start with a letter or the underscore character
  • A variable name cannot start with a number
  • A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ )
  • Variable names are case-sensitive (age, Age and AGE are three different variables)
  • The reserved words (keywords) cannot be used naming the variable
  • Variable names should be short but descriptive
  • Use of underscores (_) is recommended to improve readability
  • Avoid using special characters like !, @, #, $, %, etc. in variable names
  • Avoid using built-in function names as variable names
  • Avoid using single characters like l, O, I, etc. as variable names
  • Avoid using words with double meaning like list, str, dict, etc. as variable names
  • Avoid using words with different spellings like colour and color, centre and center , etc. as variable names
variable.py
# Valid variable names
name = "John"
my_name = "John"
_my_name = "John"
myName = "John"
MYNAME = "John"
myname = "John"
myName2 = "John"
my2name = "John"

Constants are usually declared and assigned in a module. Python does not have built-in constant types, but Python programmers use all capital letters to indicate a variable should be treated as a constant and never be changed after it is initialized.

constant.py
# Valid constant names
PI = 3.14
GRAVITY = 9.8
PLANET = "Earth"

Function names should be lowercase, with words separated by underscores as necessary to improve readability. Mixed case is allowed only in contexts where that’s already the prevailing style (e.g. threading.py), to retain backwards compatibility.

function.py
# Valid function names
def my_function():
    pass
 
def myFunction():
    pass

Class names should normally use the CapWords convention.

class.py
# Valid class names
class MyClass:
    pass

Python has a set of naming conventions for different types of identifiers. These conventions are defined in PEP 8 — Style Guide for Python Code, which is the style guide that most Python projects follow.

There are different naming styles for different types of identifiers. The following table summarizes the naming conventions for different types of identifiers:

Starts each word with a capital letter except the first word. For example: firstName, lastName, getFirstName(), setFirstName(), etc.

variable.py
# Camel Case
firstName = "John"
lastName = "Doe"
def getFirstName():
    pass
def setFirstName():
    pass

Starts each word with a capital letter. For example: FirstName, LastName, GetFirstName(), SetFirstName(), etc.

variable.py
# Pascal Case
FirstName = "John"
LastName = "Doe"
def GetFirstName():
    pass
def SetFirstName():
    pass

Uses underscores (_) between words. For example: first_name, last_name, get_first_name(), set_first_name(), etc.

variable.py
# Snake Case
first_name = "John"
last_name = "Doe"
def get_first_name():
    pass
def set_first_name():
    pass

The three styles above all run, but Python’s official style guide (PEP 8) assigns a specific style to each kind of identifier. Following it makes your code look like everyone else’s Python.

IdentifierConventionExample
Variablesnake_caseuser_age, total_price
Functionsnake_caseget_user(), calc_total()
ConstantUPPER_SNAKE_CASEMAX_SIZE, PI
ClassPascalCase (CapWords)BankAccount, UserProfile
Module / fileshort lowercaseutils.py, data_loader.py

The underscore carries special meaning in several naming patterns:

PatternMeaning
_name“Internal use” hint — a weak private signal to other developers.
name_Trailing underscore to avoid clashing with a keyword, e.g. class_, type_.
__nameName mangling inside a class — Python rewrites it to avoid subclass clashes.
__name__“Dunder” (double underscore) — reserved for Python, e.g. __init__, __name__.
_A throwaway variable for values you intend to ignore: for _ in range(3):.
underscores.py
_internal = "use within this module"
class_ = "Biology 101"     # avoids the 'class' keyword
for _ in range(3):         # loop counter is unused
    print("hi")

Underscores are a language feature, not only a style

Section titled “Underscores are a language feature, not only a style”

Three of the four underscore conventions are pure convention. One of them changes what the compiler does:

diagram Diagram mermaid
mangling.py
class C:
    def __init__(self):
        self.public = 1
        self._internal = 2
        self.__private = 3
 
c = C()
print(list(vars(c)))     # ['public', '_internal', '_C__private']
c.__private              # AttributeError
c._C__private            # 3

The attribute was renamed at compile time to _C__private. This is not access control — the value is trivially reachable — it is collision avoidance, so a subclass defining its own __private cannot clobber the parent’s.

Reserved, soft-reserved, and merely conventional

Section titled “Reserved, soft-reserved, and merely conventional”
keywords.py
import keyword
 
len(keyword.kwlist)              # 35 hard keywords: def, class, if, ...
keyword.softkwlist               # ['_', 'case', 'match', 'type']
keyword.iskeyword("match")       # False  <- a SOFT keyword; usable as a name
keyword.iskeyword("def")         # True   <- `def = 1` is a SyntaxError

There are 35 hard keywords you cannot use as names, and four soft keywords that are only special in context — match and case are ordinary identifiers everywhere else, which is how match could be added without breaking existing code.

Type-check a name against the rules Python actually enforces, and the ones PEP 8 merely recommends. Click a name to see which of each it satisfies.

sketch What Python enforces, and what PEP 8 suggests p5.js
Only two rules are enforced by the language: the character set and the keyword list. Everything about casing is convention that tools check, not the interpreter.

Identifiers are normalised before they are compared

Section titled “Identifiers are normalised before they are compared”

This one surprises almost everyone. Python applies NFKC normalisation to identifiers, so two different sequences of characters can be the same name:

nfkc.py
import unicodedata
unicodedata.normalize("NFKC", "\ufb01")     # 'fi'  — the ligature becomes two letters
 
# a name written with U+FB01 (the 'fi' ligature) is reachable as plain ascii 'fi'

A variable written with the typographic ligature and one written fi are the same variable. Not every lookalike normalises, though — the dotless ı (U+0131) stays distinct from i.

kindconventionexample
variable, functionlower_snake_caseuser_count, parse_row
constantUPPER_SNAKE_CASEMAX_RETRIES
classCapWordsHttpClient
internal_leading_underscore_cache
avoid a keyword clashtrailing_underscore_class_, id_
moduleshort lowercaseutils, http

Note the last row of the previous section: shadowing a builtin such as list, id, type or sum is perfectly legal and never warns. class_ with a trailing underscore is the documented way to name something that would otherwise collide.

pch.quizTag pch.quizDefaultTitle
  1. Inside class C, you assign self.__private = 3. What key appears in vars(instance)?

    pch.quizShowAnswer

    C — _C__private — The compiler mangles a double-underscore name to _ClassName__name. It exists to stop a subclass accidentally reusing the same attribute name, not to enforce privacy — _C__private is readable by anyone.

  2. Which of these is a SOFT keyword, meaning it is reserved only in certain positions?

    pch.quizShowAnswer

    B — match — match, case, type and _ are soft keywords: special inside a match statement and ordinary identifiers elsewhere. That is how match could be added without breaking code that used it as a variable.

  3. A contributor submits code where a name is written with the typographic ligature for 'fi'. What does Python do?

    pch.quizShowAnswer

    C — normalises identifiers with NFKC, so it is the SAME name as the ascii spelling — Identifiers are NFKC-normalised, so the ligature becomes 'fi'. Two names can look different and be identical — a reason to restrict identifiers to ASCII in projects taking outside contributions.

  4. Which naming rule does the interpreter actually enforce?

    pch.quizShowAnswer

    C — a name may not start with a digit and may not be one of the 35 reserved keywords — Only the character set and the keyword list are enforced. Every casing rule is PEP 8 convention, checked by linters rather than by the interpreter.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading