HOWTO · Python
Constant in Python
Learn how to define Python constants with UPPER_CASE names, group related values, and use Enum when Python should reject invalid members.
On this page
Python has no const declaration that makes a name permanently read-only. The usual solution is to define a module-level name with an UPPER_CASE spelling and treat reassignment as a code-review error. Use a class to group related values, or use Enum when the values form a fixed set of named members and callers should not substitute arbitrary members.
Define module-level constants with UPPER_CASE names
Put values shared by a module or package near the top of the module and spell their names in uppercase with underscores. Other modules can import the name normally. This convention communicates intent, but Python still allows the name to be rebound.
TIMEOUT_SECONDS = 30
SUPPORTED_FORMATS = ("json", "toml")
print(TIMEOUT_SECONDS)
TIMEOUT_SECONDS = 60 # Legal Python, but a reassignment of a constant by convention.
print(TIMEOUT_SECONDS)
Output:
30
60
The tuple prevents changes to that particular tuple object, but it does not make the module name immutable: SUPPORTED_FORMATS can still be rebound. Likewise, a mutable value such as a list can be changed in place. Choose immutable values where practical, and keep constants in a module when they are part of that module’s public configuration or API.
Group related values with a class
A class can provide a readable namespace for related values, accessed as Settings.DEFAULT_TIMEOUT. This is useful for organization, but a normal class attribute is not a language-enforced constant. Both the class and (usually) its instances can be modified.
class Settings:
DEFAULT_TIMEOUT = 30
RETRY_LIMIT = 3
print(Settings.DEFAULT_TIMEOUT)
Settings.DEFAULT_TIMEOUT = 60
print(Settings.DEFAULT_TIMEOUT)
Output:
30
60
Custom descriptors or metaclasses can reject selected assignments, but they add complexity and still require careful handling of instance attributes, subclassing, and other mutation paths. Do not use a plain class merely because it appears to prevent reassignment; use it as a namespace unless you have a tested, explicit enforcement requirement.
Use Enum for a fixed set of named values
Use the standard-library enum module when a value must be one of a defined set of members. An Enum member is accessed through the class, and assigning a new member value raises an exception. Enum is a better fit than an uppercase variable when the set itself has domain meaning, such as states, colors, or modes.
from enum import Enum
class Color(Enum):
RED = "red"
BLUE = "blue"
print(Color.RED.value)
try:
Color.RED = "green"
except AttributeError as error:
print(type(error).__name__)
Output:
red
AttributeError
Enum does not make every value in a program immutable, and it is not interchangeable with the raw string values. Use Color.RED when the member identity matters, or Color.RED.value when an API requires the underlying value. To parse external input, construct the enum with Color("red"); an unknown value raises ValueError, giving you an explicit boundary to handle.
Consider named tuples and functions as alternatives
The older collections.namedtuple() technique can group immutable fields: Constants = namedtuple("Constants", "PI E") followed by values = Constants(3.14159, 2.71828) creates a tuple whose fields cannot be assigned. It is still useful when the data should behave like a lightweight record, but it does not prevent rebinding values and is less expressive than Enum for named choices.
A function that returns a value can hide construction or compute a value on demand, but it is not a constant declaration. For example, def api_version(): return "v1" communicates an accessor, not an immutable binding. Prefer a module-level name for a simple constant, a class for grouping, and Enum for a closed set of related members.
Choose and verify the pattern
Use UPPER_CASE module names for ordinary shared values, a class when a namespace improves organization, and Enum for a fixed domain set. In every case, state the mutation boundary clearly: ordinary names and class attributes can be rebound, while enum members reject reassignment. The examples above verify both successful access and the important failure or reassignment behavior. Python’s convention is deliberately lightweight, so reviews, tests, and clear APIs remain part of enforcing constant-like design.
Summary
Python does not provide a built-in const keyword. Define ordinary constants with module-level UPPER_CASE names, group related constants with a class when helpful, and choose Enum when callers should use one of several named members. Treat namedtuple() and function accessors as specialized alternatives rather than as enforced constants.