Python Naming Conventions for Variables

Python naming conventions for variables come down to one PEP 8 rule: write variable names in lowercase snake_case, like sales_tax or order_total. Constants get UPPER_CASE, and classes get CapWords.

On top of that style rule, Python itself rejects some names outright, such as ones that start with a digit or match a keyword.

In this article, I’ll show you both sets of rules on one list of sample names, the real errors bad names cause, and two quick ways to check your own code. I ran everything on Python 3.12.5.

The sample variable names we’ll check

Here’s the list I’ll use throughout. They’re names you’d plausibly type in a small US store script:

  • Good names: sales_tax, MAX_ORDERS, _cache
  • Valid but un-Pythonic: zipCode (camelCase)
  • Broken: 2026_revenue, class, first-name, total$
  • Valid but risky: list, which hides a built-in

That last group matters most, because Python accepts those names and the bug shows up later. If variables themselves are new to you, start with variables in Python.

What makes a variable name valid in Python?

Python’s hard rules are short: start with a letter or underscore, use only letters, digits and underscores, and skip keywords. Names are case-sensitive, so total and Total differ.

Let me show you what happens when the four broken names hit the interpreter:

lines = ['2026_revenue = 48250.00',
         'class = "Premium"',
         'first-name = "Megan"',
         'total$ = 19.99']

for src in lines:
    try:
        compile(src, "orders.py", "exec")
    except SyntaxError as err:
        print(f"{src:<26} SyntaxError: {err.msg}")

class_ = "Premium"          # trailing underscore dodges the keyword
revenue_2026 = 48250.00     # digits are fine after the first letter
print(class_, f"${revenue_2026:,.2f}")

Output:

2026_revenue = 48250.00    SyntaxError: invalid decimal literal
class = "Premium"          SyntaxError: invalid syntax
first-name = "Megan"       SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='?
total$ = 19.99             SyntaxError: invalid syntax
Premium $48,250.00

All four fail with a SyntaxError, while class_ and revenue_2026 work fine.

Command Prompt output of Python raising SyntaxError for variable names that start with a digit, use a keyword, a hyphen or a dollar sign
Each broken name raises a SyntaxError with its own message, and the fixed names print Premium and $48,250.00.

How does this code work?

2026_revenue looks like a number to the parser, hence “invalid decimal literal”. first-name reads as first minus name, and you can’t assign to a subtraction.

compile() parses each line without running it. So here’s the catch: no message says “bad variable name”, so check the name first.

PEP 8 naming conventions for variables, constants and classes

Valid isn’t the same as Pythonic. zipCode runs, but PEP 8 asks for zip_code. Here’s the style for each kind of name, with the matching sample name:

Kind of namePEP 8 styleExample
Variablelowercase_with_underscoressales_tax
Constant (module level)UPPER_CASE_WITH_UNDERSCORESMAX_ORDERS
ClassCapWordsOrderItem
Internal useone leading underscore_cache
Clashes with a keywordone trailing underscoreclass_
Name-mangled attributetwo leading underscoresself.__pin

PEP 8 also says never to use l, O or I as single-letter names; they look like 1 and 0 in some fonts. Constants get their own guide in constants in Python.

One leading underscore is only a hint, while two inside a class trigger name mangling: self.__pin is stored as _Account__pin. That avoids subclass clashes; it isn’t security. See private variables in Python.

Pro Tip: Function, module and package names follow similar rules. I cover those in Python naming conventions, so this page sticks to variables.

Why does naming a variable list break your code?

list, sum, id and type aren’t keywords, so Python lets you reuse them, hiding the original function.

Here’s the code:

list = ["Austin", "Denver", "Boise"]     # shadows the built-in list
print(list)

try:
    cities = list(("Tampa", "Reno"))
except TypeError as err:
    print("TypeError:", err)

del list                                  # removes the shadow
print(list(("Tampa", "Reno")))

Output:

['Austin', 'Denver', 'Boise']
TypeError: 'list' object is not callable
['Tampa', 'Reno']

The second call fails with “‘list’ object is not callable”, and works again after del list.

Command Prompt output of Python showing TypeError list object is not callable after a variable named list shadows the built-in
Once list holds the city names, calling list() raises a TypeError; after del list, the built-in works again.

How does this code work?

The assignment makes list point to your three cities. The next list(...) tries to call that list, which isn’t a function.

The fix is a better name like cities. A total named sum breaks the same way, as shown in the sum() function in Python.

Method 1: Check variable names with isidentifier() and iskeyword()

When names come from data, like CSV headers, check them in code. str.isidentifier() tests the syntax rules and keyword.iskeyword() catches keywords. Here’s the checker on all nine names:

import builtins
import keyword

names = ["sales_tax", "zipCode", "2026_revenue", "class", "first-name",
         "MAX_ORDERS", "_cache", "list", "total$"]

for name in names:
    if keyword.iskeyword(name):
        verdict = "keyword, not allowed"
    elif not name.isidentifier():
        verdict = "invalid identifier"
    elif hasattr(builtins, name):
        verdict = "valid, but shadows a built-in"
    else:
        verdict = "valid"
    print(f"{name:<14} {verdict}")

Output:

sales_tax      valid
zipCode        valid
2026_revenue   invalid identifier
class          keyword, not allowed
first-name     invalid identifier
MAX_ORDERS     valid
_cache         valid
list           valid, but shadows a built-in
total$         invalid identifier

Three names are invalid, one is a keyword, and list is flagged as shadowing a built-in.

Command Prompt output of a Python script checking nine variable names with isidentifier, iskeyword and the builtins module
The checker labels each sample name as valid, invalid, a keyword, or a name that shadows a built-in.

How does this code work?

The keyword test runs first, because "class".isidentifier() is actually True. Then hasattr(builtins, name) spots names like list.

Note that zipCode passes: the checker tests what’s legal, not PEP 8 style. Here’s a related trick for checking the type of a variable.

Method 2: Catch bad variable names with Ruff (Recommended)

For style, let a linter do it. Ruff (pip install ruff) has pep8-naming rules (N), the ambiguous-name rule E741, and built-in shadowing rules (A). Here’s a file full of bad names:

l = [19.99, 4.50]
O = 0


def GetOrderTotal(prices):
    orderTotal = sum(prices)
    return orderTotal


class order_item:
    pass


list = ["Austin", "Denver"]

Output:

bad_names.py:1:1: E741 Ambiguous variable name: `l`
bad_names.py:2:1: E741 Ambiguous variable name: `O`
bad_names.py:5:5: N802 Function name `GetOrderTotal` should be lowercase
bad_names.py:6:5: N806 Variable `orderTotal` in function should be lowercase
bad_names.py:10:7: N801 Class name `order_item` should use CapWords convention
bad_names.py:14:1: A001 Variable `list` is shadowing a Python builtin
Found 6 errors.

Ruff reports six problems, one per bad name.

Command Prompt output of ruff check flagging ambiguous variable names l and O, a camelCase function and variable, a lowercase class and a shadowed list
Ruff flags l and O, the camelCase function and variable, the snake_case class name and the variable named list.

How does this code work?

--select N,E741,A turns on just the naming rules, and --output-format concise prints one line per issue. N806 caught orderTotal inside the function.

I run it before every commit. Names also decide where a variable lives, which Python variable scope explains.

Things to Keep in Mind When Naming Python Variables

  • A SyntaxError on an assignment usually means a bad name. Start with a letter or underscore and drop hyphens and symbols.
  • Built-in names are legal but hide the function. Rename list, sum or id to something descriptive.
  • Keywords can’t be names. Add a trailing underscore, like class_.
  • PEP 8 is a style guide. If your project already uses another style, stay consistent with it.

Want to keep going with variables? These pick up where this one stops:

Frequently asked questions

What is the naming convention for variables in Python?

PEP 8 says lowercase words joined by underscores (snake_case), like order_total.

Should Python variables use camelCase?

No. camelCase works, but PEP 8 allows mixedCase only where a module already uses it.

Can a Python variable name start with a number?

No. It raises a SyntaxError; use revenue_2026 instead of 2026_revenue.

How do I check if a string is a valid variable name?

Use name.isidentifier() and not keyword.iskeyword(name).

Why shouldn’t I name a variable list or sum?

It hides the built-in function, so later calls fail with “object is not callable”.

Where are Python’s naming conventions documented?