If you have written even a handful of Python scripts, you have probably assigned a value to a name and expected it to stay the same for the rest of the program. That name is a constant. Understanding how Python handles constants, and why it does so differently from languages like C++ or Java, is one of the first building blocks of writing clean, readable code.
Every program contains values that should never change while the code runs. A database port number, the mathematical value of pi, or the maximum number of login attempts are all examples. In many languages these values are locked down with a keyword like const or final. Python takes a different path: it relies on a naming convention and the discipline of every developer on the team. This tutorial walks through the concept from scratch, shows you the convention, introduces the tools that can add guardrails, and gives you practice exercises along the way.
What Is a Constant and Why Does Python Need One?
A constant is a value that stays fixed for the entire lifetime of a program. Think of it as a label you attach to a piece of data with an agreement that the label will always point to the same thing. In contrast, a regular variable can be reassigned to a new value at any time.
Consider a program that calculates the area of a circle. The formula requires pi, and pi never changes. If you wrote 3.14159 directly into every formula, you would have a "magic number" scattered across your code. If you later needed more decimal places, you would have to hunt down every occurrence and update it. A constant solves this by giving that value a single, descriptive name.
# Without a constant — magic number scattered in code
area = 3.14159 * radius ** 2
circumference = 2 * 3.14159 * radius
# With a constant — single source of truth
PI = 3.14159
area = PI * radius ** 2
circumference = 2 * PI * radius
Constants improve readability because a reader can see PI and immediately understand what the value represents. They improve maintainability because changing the value requires editing a single line. And they reduce errors because there is no risk of mistyping a number deep inside a formula.
Python does not have a built-in const keyword. The word "constant" in Python refers to a variable that developers agree not to change, signaled entirely by how the name is written.
Variables vs. Constants at a Glance
A variable is a name you expect to reassign during execution. A constant is a name you expect to remain fixed. Both are created the same way in Python, with a simple assignment statement, but they follow different naming conventions so readers can tell them apart.
# Variable — lowercase with underscores (snake_case)
user_count = 0
user_count = user_count + 1 # reassignment is expected
# Constant — ALL UPPERCASE with underscores
MAX_USERS = 500
# MAX_USERS should never be reassigned
Build a valid Python constant assignment for the speed of light in meters per second:
How Python Handles Constants: Convention Over Enforcement
Python's philosophy leans toward trusting developers rather than restricting them. Instead of a compiler refusing to let you change a value, Python relies on the ALL_UPPERCASE naming convention described in PEP 8, the official style guide. When you see a name written entirely in capital letters with underscores between words, you know the author intends it to be a constant.
# PEP 8 constant naming convention
MAX_RETRIES = 3
DATABASE_PORT = 5432
DEFAULT_TIMEOUT = 30
API_BASE_URL = "https://api.example.com/v2"
Nothing in the Python interpreter stops you from writing MAX_RETRIES = 99 later in the same file. The convention is a social contract: every developer on the team agrees to treat uppercase names as read-only. This approach is sometimes called "convention over enforcement," and it fits naturally with Python's dynamic nature.
Define constants at the top of your module, right after import statements. This makes them easy to find and shows readers immediately what fixed values the module depends on.
Organizing Constants in Larger Projects
For small scripts, keeping constants at the top of a single file works well. As a project grows, a dedicated constants.py module is a common pattern. Other modules import the values they need, and the entire team knows exactly where to look when a configuration value needs reviewing.
# constants.py
MAX_CONNECTIONS = 100
TIMEOUT_SECONDS = 30
LOG_LEVEL = "INFO"
# app.py
from constants import MAX_CONNECTIONS, TIMEOUT_SECONDS
- Reassignable?
- Technically yes, but by convention you never should.
- Example
MAX_RETRIES = 3
- Reassignable?
- Yes, reassignment is expected during program execution.
- Example
retry_count = 0
- Reassignable?
- Not applicable. A literal is the raw value itself, not a name.
- Example
3.14159,"hello",42
The code below tries to define and use a constant. One line violates the naming convention. Click the line you think is wrong, then hit check.
Max_Speed) instead of ALL_UPPERCASE. If the intent is to reassign the constant, that breaks the convention entirely. If the intent is a new constant, it should be written as MAX_SPEED. Mixed-case names are neither proper variable names (snake_case) nor proper constant names (ALL_UPPERCASE), creating confusion for every reader.
Built-in Constants and typing.Final
Python ships with a handful of built-in constants that you use every day, even if you have not thought of them that way. True, False, and None are all constant values. They are singletons, meaning each exists as exactly one object in memory, and they cannot be reassigned in modern Python.
The standard library also provides mathematical constants through the math module. math.pi returns 3.141592653589793, math.e returns Euler's number, math.tau gives the full circle constant (2 times pi), and math.inf represents positive infinity.
import math
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
print(math.tau) # 6.283185307179586
print(math.inf) # inf
Enforcing Constants with typing.Final
Starting with Python 3.8, PEP 591 introduced typing.Final as a way to tell type checkers that a name should not be rebound. When you annotate a name with Final, tools like mypy will report an error if any later line tries to reassign it. The Python interpreter itself does not enforce this at runtime, but a type checker running as part of your development workflow will catch the mistake before the code ships.
from typing import Final
MAX_CONNECTIONS: Final = 100
DATABASE_PORT: Final[int] = 5432
# This runs fine in Python, but mypy will flag it:
MAX_CONNECTIONS = 200 # error: Cannot assign to final name
Final prevents the name from being rebound. It does not make the value immutable. If you assign a list to a Final name, the list's contents can still change. Combine Final with an immutable container like a tuple when you need both protections.
Other Approaches to Immutability
Beyond typing.Final, Python offers several ways to make values harder to change. The enum module lets you define a group of named constants as members of a class, and those members cannot be reassigned. A namedtuple produces a lightweight, immutable object. A frozen dataclass, created with @dataclass(frozen=True), raises an error if you try to modify any attribute after creation.
from enum import Enum
class Direction(Enum):
NORTH = "N"
SOUTH = "S"
EAST = "E"
WEST = "W"
print(Direction.NORTH) # Direction.NORTH
print(Direction.NORTH.value) # N
# Direction.NORTH = "UP" # raises AttributeError
How to Define Constants in Python
Follow these three steps whenever you need to introduce a constant into your Python program.
-
Choose a descriptive ALL_UPPERCASE name
Pick a name that clearly communicates the value's purpose. Write every letter in uppercase and separate words with underscores. For example, use
MAX_CONNECTIONSinstead of an abbreviation likeMC. Avoid starting the name with a digit, and only use letters, digits, and underscores. -
Place the constant at the top of the module
Define the constant after your import statements and before any function or class definitions. This makes the value easy to find and signals that it is module-level configuration. For larger projects, consider a dedicated
constants.pyfile. -
Assign the value and optionally annotate with Final
Assign the fixed value with a simple equals sign. If your project uses type checking, import
Finalfromtypingand annotate the constant so tools like mypy will flag accidental reassignment. Example:MAX_RETRIES: Final = 3.
Python Learning Summary Points
- A constant is a value intended to remain unchanged. Python signals this through the ALL_UPPERCASE naming convention described in PEP 8, not through a language keyword.
- Python's built-in constants include
True,False,None, and values from themathmodule likemath.piandmath.e. typing.Final(Python 3.8+) lets type checkers catch reassignment errors, but it does not enforce immutability at runtime. For full protection, pair it with immutable containers or useEnumand frozen dataclasses.- Place constants at the top of your module or in a dedicated
constants.pyfile, and always use descriptive names that make the value's purpose clear without needing a comment.
Constants are a small concept with outsized impact on code quality. Getting into the habit of naming fixed values in ALL_UPPERCASE, placing them prominently at the top of your files, and reaching for Final when type checking is available will make your programs easier to read, maintain, and trust.
Frequently Asked Questions
A constant in Python is a variable whose value is intended to stay the same throughout the life of a program. Python does not have a dedicated const keyword, so constants are signaled by writing the name in ALL_UPPERCASE letters with underscores separating words.
No. Python does not prevent you from reassigning a constant at runtime. The ALL_UPPERCASE naming convention is a social contract between developers. Tools like mypy can enforce typing.Final annotations at the type-checking level, but the interpreter itself will not raise an error if you change the value.
PEP 8 says constants should be written in all uppercase letters with underscores separating words, such as MAX_RETRIES or DATABASE_PORT. This convention makes constants visually distinct from regular variables.
typing.Final is a special type qualifier introduced in Python 3.8 via PEP 591. It tells type checkers like mypy that a name should not be reassigned. It does not enforce immutability at runtime but will cause type checkers to report an error if the name is rebound.
A variable is a name that can be reassigned to different values as a program runs. A constant is a variable whose value is intended to remain fixed. In Python both are created the same way with assignment, but constants use ALL_UPPERCASE names to signal that their values should not change.
Constants are typically defined at the top of a module, after import statements and before function or class definitions. For larger projects, you can create a dedicated constants.py module and import values from it wherever needed.
Python ships with several built-in constants including True, False, and None. The math module adds mathematical constants such as math.pi, math.e, math.tau, math.inf, and math.nan. These values are predefined and available without creating them yourself.
Python does not support truly immutable name bindings, but you can approximate immutability using techniques such as namedtuple, frozen dataclasses with the @dataclass(frozen=True) decorator, or custom classes that override __setattr__ to prevent reassignment.
The enum module lets you define a group of related named constants as members of an Enum class. Enum members are read-only and cannot be reassigned, making them a practical way to group a fixed set of values such as days of the week or status codes.
No. typing.Final only prevents the name from being rebound to a new object. If the value is a mutable type like a list or dictionary, its contents can still change. To prevent both rebinding and mutation, combine Final with an immutable container such as a tuple.