Question Comment créer une constante en Python?


Existe-t-il un moyen de déclarer une constante en Python? En Java, nous pouvons créer des valeurs constantes de cette manière:

public static final String CONST_NAME = "Name";

Quel est l'équivalent de la déclaration de constante Java ci-dessus en Python?


714
2018-04-21 12:20


origine


Réponses:


Non, il n'y en a pas. Vous ne pouvez pas déclarer une variable ou une valeur comme constante dans Python. Ne le change pas.

Si vous êtes dans une classe, l'équivalent serait:

class Foo(object):
    CONST_NAME = "Name"

sinon, c'est juste

CONST_NAME = "Name"

Mais vous voudrez peut-être jeter un oeil à l'extrait de code Constantes en Python par Alex Martelli.


725
2018-04-21 12:21



Il n'y a pas const mot-clé comme dans d'autres langues, mais il est possible de créer une propriété a une "fonction getter" lire les données, mais pas de "fonction de réglage" réécrire les données. Cela protège essentiellement l'identifiant d'être changé.

Voici une implémentation alternative utilisant la propriété de classe:

Notez que le code est loin d'être facile pour un lecteur qui s'interroge sur les constantes. Voir l'explication ci-dessous

def constant(f):
    def fset(self, value):
        raise TypeError
    def fget(self):
        return f()
    return property(fget, fset)

class _Const(object):
    @constant
    def FOO():
        return 0xBAADFACE
    @constant
    def BAR():
        return 0xDEADBEEF

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

Explication du code:

  1. Définir une fonction constant cela prend une expression, et l'utilise pour construire un "getter" - une fonction qui retourne uniquement la valeur de l'expression.
  2. La fonction setter déclenche une erreur TypeError qui est en lecture seule
  3. Utilisez le constant fonction que nous venons de créer comme une décoration pour définir rapidement les propriétés en lecture seule.

Et d'une autre manière plus démodée:

(Le code est assez difficile, plus d'explications ci-dessous)

class _Const(object):
    @apply
    def FOO():
        def fset(self, value):
            raise TypeError
        def fget(self):
            return 0xBAADFACE
        return property(**locals())

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

Notez que le décorateur @apply semble être obsolète.

  1. Pour définir l'identifiant FOO, les premiers définissent deux fonctions (fset, fget - les noms sont à mon choix).
  2. Ensuite, utilisez le built-in property fonction pour construire un objet qui peut être "set" ou "get".
  3. Remarquez le chapeau property Les deux premiers paramètres de la fonction sont nommés fset et fget.
  4. Utilisez le fait que nous avons choisi ces mêmes noms pour notre propre getter & setter et créer un dictionnaire de mots-clés en utilisant le ** (double astérisque) appliqué à toutes les définitions locales de cette portée pour passer des paramètres à la property fonction

294
2018-04-22 03:39



En Python, au lieu d'appliquer un langage, les gens utilisent des conventions de dénomination, par exemple __method pour des méthodes privées et en utilisant _method pour les méthodes protégées.

Donc, de la même manière, vous pouvez simplement déclarer la constante comme toutes les majuscules, par ex.

MY_CONSTANT = "one"

Si vous voulez que cette constante ne change jamais, vous pouvez vous connecter à l'accès aux attributs et faire des trucs, mais une approche plus simple consiste à déclarer une fonction

def MY_CONSTANT():
    return "one"

Le seul problème est partout où vous devrez faire MY_CONSTANT (), mais encore MY_CONSTANT = "one" est le bon chemin en python (habituellement).

Vous pouvez aussi utiliser namedtuple pour créer des constantes:

>>> from collections import namedtuple
>>> Constants = namedtuple('Constants', ['pi', 'e'])
>>> constants = Constants(3.14, 2.718)
>>> constants.pi
3.14
>>> constants.pi = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

82
2018-04-21 13:06



Je manque probablement un tour ici, mais cela semble fonctionner pour moi:

class CONST(object):
    FOO = 1234

    def __setattr__(self, *_):
        pass

CONST = CONST()

#----------

print CONST.FOO    # 1234

CONST.FOO = 4321
CONST.BAR = 5678

print CONST.FOO    # Still 1234!
print CONST.BAR    # Oops AttributeError

Créer l'instance permet la magie __setattr__ méthode pour lancer et intercepter les tentatives pour définir la FOO variable. Vous pourriez lancer une exception ici si vous le souhaitez. L'instanciation de l'instance sur le nom de la classe empêche l'accès directement via la classe.

C'est une douleur totale pour une valeur, mais vous pouvez attacher beaucoup à votre CONST objet. Avoir une classe supérieure, le nom de la classe semble aussi un peu minable, mais je pense que c'est globalement assez succinct.


31
2018-04-24 16:00



En plus des deux meilleures réponses (utilisez simplement des variables avec des noms UPPERCASE, ou utilisez des propriétés pour rendre les valeurs en lecture seule), je tiens à mentionner qu'il est possible d'utiliser des métaclasses pour implémenter nommé constantes. Je fournis une solution très simple en utilisant des métaclasses à GitHub ce qui peut être utile si vous voulez que les valeurs soient plus informatives sur leur type / nom:

>>> from named_constants import Constants
>>> class Colors(Constants):
...     black = 0
...     red = 1
...     white = 15
...
>>> c = Colors.black
>>> c == 0
True
>>> c
Colors.black
>>> c.name()
'black'
>>> Colors(0) is c
True

C'est un peu plus avancé en Python, mais toujours très facile à utiliser et à portée de main. (Le module a plus de fonctionnalités, y compris les constantes en lecture seule, voir son fichier README.)

Il y a des solutions similaires qui circulent dans divers dépôts, mais au meilleur de ma connaissance, elles manquent d'une des caractéristiques fondamentales que j'attendrais des constantes (comme être constantes, ou être de type arbitraire), ou elles ont des caractéristiques ésotériques ajoutées les rendre moins généralement applicables. Mais YMMV, je serais reconnaissant pour les commentaires. :-)


15
2017-10-10 21:25



Comme vous le savez probablement déjà, Python n'a pas de constantes :(

L'alternative la plus simple est peut-être de définir une fonction pour cela. Par exemple.

def MY_CONSTANT():
    return 42

MY_CONSTANT() a maintenant toutes les fonctionnalités d'une constante (plus quelques accolades ennuyeuses).


13
2017-09-08 22:01



Edit: Ajout d'un exemple de code pour Python 3

Remarque: cette autre réponse On dirait qu'il fournit une implémentation beaucoup plus complète semblable à ce qui suit (avec plus de fonctionnalités).

D'abord, faites un métaclasse:

class MetaConst(type):
    def __getattr__(cls, key):
        return cls[key]

    def __setattr__(cls, key, value):
        raise TypeError

Cela empêche les propriétés statiques d'être modifiées. Ensuite, faites une autre classe qui utilise cette métaclasse:

class Const(object):
    __metaclass__ = MetaConst

    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        raise TypeError

Ou, si vous utilisez Python 3:

class Const(object, metaclass=MetaConst):
    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        raise TypeError

Cela devrait empêcher les accessoires d'instance d'être modifiés. Pour l'utiliser, héritez:

class MyConst(Const):
    A = 1
    B = 2

Maintenant, les accessoires, accessibles directement ou via une instance, doivent être constants:

MyConst.A
# 1
my_const = MyConst()
my_const.A
# 1

MyConst.A = 'changed'
# TypeError
my_const.A = 'changed'
# TypeError

Voici un exemple de ci-dessus en action. Voici un autre exemple pour Python 3.


12
2017-10-03 00:28



Les propriétés sont un moyen de créer des constantes. Vous pouvez le faire en déclarant une propriété getter, mais en ignorant le setter. Par exemple:

class MyFinalProperty(object):

    @property
    def name(self):
        return "John"

Vous pouvez jeter un oeil à un article que j'ai écrit pour trouver plus de façons d'utiliser les propriétés Python.


6
2017-07-12 22:51