Python, unlike some other programming languages such as Java, does not have an explicit keyword to declare constants. However, there are conventions and techniques that developers follow to define values that should not change during the execution of a program.
Using Uppercase Variable Names
The most common way to indicate that a variable is intended to be a constant in Python is by naming it in all uppercase letters with words separated by underscores as needed. This convention signals to other developers (and to yourself) that this variable’s value should not be changed after it’s initialized.
MY_CONSTANT = "some_value"
Using the typing.Final
Annotation
As of Python 3.8, you can use the typing.Final
type hint to indicate that a variable is intended to be constant. This does not prevent reassignment at runtime but will cause static type checkers like mypy to report an error if they detect an attempt to reassign such a variable.
from typing import Final
MY_CONSTANT: Final = "some_value"
Creating Read-Only Properties with Classes
You can also define constants using classes and the property
decorator, which allows you to create read-only properties. Here’s how you might do it:
class Constants:
def __init__(self):
self._my_constant = "some_value"
@property
def MY_CONSTANT(self):
return self._my_constant
# Attempting to set a new value will raise an AttributeError
constants = Constants()
try:
constants.MY_CONSTANT = "new_value"
except AttributeError:
print("Cannot modify constant")
However, this approach doesn’t perfectly mimic the behavior of true constants since it relies on internal implementation details and doesn’t prevent all forms of modification (e.g., modifying the private variable directly).
Using namedtuple
for Constants
Another creative way to define constants is by using namedtuple
, which creates an immutable object. This can be particularly useful when you need a collection of related constant values.
from collections import namedtuple
Constants = namedtuple('Constants', ['PI', 'E'])
constants = Constants(3.14, 2.718)
print(constants.PI) # prints: 3.14
# Attempting to modify will raise an AttributeError
try:
constants.PI = 3
except AttributeError:
print("Cannot modify constant")
Preventing Modification with __slots__
and Class Definition
For a more robust approach, especially when dealing with single values or small sets of named constants, you can define a class that uses __slots__
to prevent additional attributes from being added and override methods like __setattr__
to control attribute modification.
class Const:
__slots__ = ('FOO',)
def __init__(self):
self.FOO = 1234
def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError(f"Cannot modify constant {name}")
super().__setattr__(name, value)
const = Const()
# Attempting to modify will raise an AttributeError
try:
const.FOO = 4321
except AttributeError as e:
print(e) # prints: Cannot modify constant FOO
Conclusion
While Python does not have built-in support for constants in the same way languages like Java do, you can effectively communicate your intent and enforce immutability through a combination of naming conventions, type hints, class definitions, and creative use of built-in data structures. Remember, the key to successfully using "constants" in Python is understanding that enforcement is more about convention and developer discipline than strict language rules.