At first, this question might sound contradictory—after all, isn’t the whole point of a constant that its value doesn’t change?
In theory, yes. But in practice, things are a bit different. Python doesn’t have a built-in way to define constants. Instead, by convention, we assign a value to a regular variable and write its name in all uppercase letters to indicate that it should not be modified. However, this is just a naming convention, not actual protection. Python won’t stop anyone from reassigning the value.
But that doesn’t mean we have to accept it. If you’re worried about constants being changed—accidentally or otherwise—there are several ways to make them effectively immutable in Python.
Here are three approaches:
1. Using namedtuple fields
This approach uses a namedtuple, where each field represents a constant. The defaults argument sets their values.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import math from collections import namedtuple Constants = namedtuple('Constants', 'pi π e euler_number', defaults=(math.pi, math.pi, math.e, math.e))() # TEST print(Constants.pi, Constants.π, Constants.e, Constants.euler_number) # Output: # 3.141592653589793 3.141592653589793 2.718281828459045 2.718281828459045 Constants.pi = 3.14 # Output: AttributeError: can't set attribute |
This example also shows that a constant can be referenced using different names. You can even use Greek letters commonly used in mathematics (such as π), since Python allows identifiers to contain Unicode characters. (This topic was discussed in a previous post.)
2. Defining Constants as Read-Only Properties in a Class
Here, constants are defined as read-only properties inside a class. Any attempt to overwrite them raises an error.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class Constants: @property def h(self): """Planck's constant.""" return 6.62607015E-34 @property def g(self): """Acceleration due to gravity.""" return 9.80665 # TEST const = Constants() print(const.h, const.g) # Output: 6.62607015e-34 9.80665 const.h = 6 # Output: AttributeError: can't set attribute |
3. Using a dataclass with frozen=True
In this solution, constants are defined as fields of a dataclass that is marked as frozen, which makes all attributes read-only after instantiation.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from dataclasses import dataclass @dataclass(frozen=True) class Constants: R = 8.31446261815324 # Universal gas constant G = 6.6742867e-11 # Gravitational constant # TEST const = Constants() print(const.R, const.G) # Output: 8.31446261815324 6.6742867e-11 const.G = 9 # Output: dataclasses.FrozenInstanceError: cannot assign to field 'G' |
All language elements used in these three approaches are explained in more detail—with examples—in the e-book Python Knowledge Building Step by Step.