HOWTO · Python

Les constantes en Python

Découvrez comment définir des constantes Python avec des noms UPPER_CASE, regrouper des valeurs et utiliser Enum pour un ensemble fixe.

Sur cette page

Python ne possède pas de déclaration const qui rende un nom définitivement non réassignable. La solution habituelle consiste à définir un nom au niveau du module avec l’écriture UPPER_CASE et à considérer sa réassignation comme une erreur de revue de code. Utilisez une classe pour regrouper des valeurs liées, ou Enum lorsque les valeurs forment un ensemble fixe de membres nommés.

Définir des constantes de module avec des noms UPPER_CASE

Placez les valeurs partagées par un module ou un paquet près du début du module et écrivez leurs noms en majuscules avec des underscores. Les autres modules peuvent importer ce nom normalement. Cette convention exprime l’intention, mais Python permet toujours de réaffecter le nom.

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)

Sortie :

30
60

Le tuple empêche les modifications de cet objet tuple précis, mais ne rend pas le nom du module immuable : SUPPORTED_FORMATS peut encore être réaffecté. De même, une valeur mutable comme une liste peut être modifiée sur place. Choisissez des valeurs immuables lorsque c’est possible et gardez les constantes dans un module lorsqu’elles font partie de sa configuration ou de son API publique.

Regrouper les valeurs liées avec une classe

Une classe peut fournir un espace de noms lisible pour des valeurs liées, accessible avec Settings.DEFAULT_TIMEOUT. C’est utile pour l’organisation, mais un attribut de classe normal n’est pas une constante imposée par le langage. La classe et (généralement) ses instances peuvent être modifiées.

class Settings:
    DEFAULT_TIMEOUT = 30
    RETRY_LIMIT = 3


print(Settings.DEFAULT_TIMEOUT)
Settings.DEFAULT_TIMEOUT = 60
print(Settings.DEFAULT_TIMEOUT)

Sortie :

30
60

Des descripteurs personnalisés ou des métaclasses peuvent refuser certaines affectations, mais ils ajoutent de la complexité et exigent toujours de traiter soigneusement les attributs d’instance, l’héritage et les autres chemins de mutation. N’utilisez pas une classe ordinaire simplement parce qu’elle semble empêcher la réaffectation ; utilisez-la comme espace de noms, sauf si une contrainte explicite et testée est nécessaire.

Utiliser Enum pour un ensemble fixe de valeurs nommées

Utilisez le module enum de la bibliothèque standard lorsqu’une valeur doit être l’un des membres définis. Un membre Enum s’obtient par la classe et lui affecter une nouvelle valeur déclenche une exception. Enum convient mieux qu’une variable en majuscules lorsque l’ensemble a un sens métier, comme des états, des couleurs ou des 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__)

Sortie :

red
AttributeError

Enum ne rend pas toutes les valeurs du programme immuables et n’est pas interchangeable avec les chaînes brutes. Utilisez Color.RED lorsque l’identité du membre compte, ou Color.RED.value lorsqu’une API exige la valeur sous-jacente. Pour analyser une entrée externe, construisez l’enum avec Color("red") ; une valeur inconnue déclenche ValueError.

Envisager les namedtuples et les fonctions comme alternatives

L’ancienne technique collections.namedtuple() peut regrouper des champs immuables : Constants = namedtuple("Constants", "PI E") puis values = Constants(3.14159, 2.71828) créent un tuple dont les champs ne peuvent pas être affectés. Elle reste utile lorsque les données doivent se comporter comme un enregistrement léger, mais elle est moins expressive qu’Enum pour des choix nommés.

Une fonction qui renvoie une valeur peut masquer sa construction ou la calculer à la demande, mais ce n’est pas une déclaration de constante. Par exemple, def api_version(): return "v1" indique un accesseur, pas une liaison immuable. Préférez un nom de module pour une constante simple, une classe pour le regroupement et Enum pour un ensemble fermé de membres associés.

Choisir et vérifier le modèle

Utilisez des noms de module UPPER_CASE pour les valeurs partagées ordinaires, une classe lorsqu’un espace de noms améliore l’organisation et Enum pour un ensemble métier fixe. Indiquez toujours la limite de mutation : les noms ordinaires et les attributs de classe peuvent être réaffectés, tandis que les membres d’Enum refusent la réaffectation. Les exemples vérifient l’accès réussi et le comportement d’échec important. Les revues, les tests et des API claires restent nécessaires pour appliquer une conception de type constante.

Résumé

Python ne fournit pas de mot-clé intégré const. Définissez les constantes ordinaires avec des noms de module UPPER_CASE, regroupez les constantes liées avec une classe si nécessaire et choisissez Enum lorsque les appelants doivent utiliser l’un de plusieurs membres nommés. Considérez namedtuple() et les accesseurs fonctionnels comme des alternatives spécialisées, pas comme des constantes imposées.