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 constante Java ci-dessus en Python?
True=False
, puis(2+2==4)==True
revenirFalse
.SyntaxError: can't assign to keyword
. Cela semble être une bonne chose.Réponses:
Non, il n'y en a pas. Vous ne pouvez pas déclarer une variable ou une valeur comme constante en Python. Ne le changez pas.
Si vous êtes dans une classe, l'équivalent serait:
sinon, c'est juste
Mais vous voudrez peut-être jeter un œil aux constantes d' extrait de code en Python d'Alex Martelli.
Depuis Python 3.8, il y a une
typing.Final
annotation de variable qui indiquera aux vérificateurs de type statique (comme mypy) que votre variable ne doit pas être réaffectée. C'est l'équivalent le plus proche de Javafinal
. Cependant, cela n'empêche pas réellement la réaffectation :la source
def MY_CONST_VALUE(): return 123
name.attribute
et peuvent contenir n'importe quelle valeur. La déclaration est facileNums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0)
, l'utilisation est simpleprint 10 + Nums.PI
, essayez de changer les résultats en exceptionNums.PI = 22
=> ValueError (..).Il n'y a pas de
const
mot-clé comme dans d'autres langues, mais il est possible de créer une propriété qui a une "fonction getter" pour lire les données, mais pas de "fonction setter" pour réécrire les données. Cela protège essentiellement l'identifiant contre toute modification.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
Explication du code:
constant
qui prend une expression et l'utilise pour construire un "getter" - une fonction qui renvoie uniquement la valeur de l'expression.constant
fonction que nous venons de créer comme décoration pour définir rapidement des propriétés en lecture seule.Et d'une autre manière plus ancienne:
(Le code est assez délicat, plus d'explications ci-dessous)
Notez que le décorateur @apply semble être obsolète.
property
fonction intégrée pour construire un objet qui peut être "défini" ou "récupéré".property
deux premiers paramètres de la fonction sont nommésfset
etfget
.property
fonctionla source
AttributeError
etTypeError
, je pense que l'exception levée devrait être une nouvelle erreur, que je propose de nommerConstantError
ou quelque chose comme ça, qui est une sous-classe deTypeError
. La section dans les documents qui me fait penser que: docs.python.org/2/library/exceptions.htmlCONST.__dict__['FOO'] = 7
En Python, au lieu d'appliquer un langage, les gens utilisent des conventions de dénomination, par exemple
__method
pour les méthodes privées et_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 exemple
Si vous voulez que cette constante ne change jamais, vous pouvez vous connecter à l'accès aux attributs et faire des tours, mais une approche plus simple consiste à déclarer une fonction
Le seul problème est partout où vous devrez faire MY_CONSTANT (), mais encore une fois
MY_CONSTANT = "one"
c'est la bonne façon en python (généralement).Vous pouvez également utiliser namedtuple pour créer des constantes:
la source
def MY_CONSTANT(): return "one"
n'arrêtera pas quelqu'un, plus tard dans le code, faisantMY_CONSTANT = "two"
(ou redéclarant la fonction).MY_CONSTANT = MY_CONSTANT()
, mais d'utiliserMY_CONSTANT()
comme constante. Bien sûr, ça. Mais cela va bien et est tout à fait conforme au principe python "Nous sommes tous des adultes ici" - c'est-à-dire qu'il sera rarement interdit au développeur de décider de remplacer une règle lorsqu'il a de bonnes raisons et sait ce qu'il fait.J'ai récemment trouvé une mise à jour très succincte qui soulève automatiquement des messages d'erreur significatifs et empêche l'accès via
__dict__
:Nous définissons sur nous-mêmes de nous faire une instance, puis utilisons des emplacements pour nous assurer qu'aucun attribut supplémentaire ne peut être ajouté. Cela supprime également la
__dict__
route d'accès. Bien sûr, tout l'objet peut encore être redéfini.Edit - Solution originale
Il me manque probablement une astuce ici, mais cela semble fonctionner pour moi:
La création de l'instance permet à la
__setattr__
méthode magique de démarrer et d'intercepter les tentatives de définition de laFOO
variable. Vous pouvez 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. Ayant une classe supérieure, le nom de classe semble aussi un peu grincheux, mais je pense que c'est assez succinct dans l'ensemble.la source
CONST.
préfixe. Dans les situations multi-modules, cela sera également compliqué.__slots__
solution est tellement élégante et efficace. D'après tout ce que j'ai lu, c'est à peu près aussi proche que possible de la création de constantes en Python. Merci beaucoup. Et pour toutes les personnes intéressées, voici une explication brillante et approfondie de la__slots__
magie.Python n'a pas de constantes.
Peut-être que l'alternative la plus simple est de lui définir une fonction:
MY_CONSTANT()
a maintenant toutes les fonctionnalités d'une constante (plus quelques accolades ennuyeuses).la source
constexpr
) sont de vraies constantes dures.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 afin d'implémenter des constantes nommées . Je fournis une solution très simple en utilisant des métaclasses sur GitHub qui peut être utile si vous voulez que les valeurs soient plus informatives sur leur type / nom:
Il s'agit de Python légèrement plus avancé, mais toujours très facile à utiliser et pratique. (Le module a quelques fonctionnalités supplémentaires, y compris les constantes en lecture seule, voir son fichier README.)
Il existe des solutions similaires flottant dans divers référentiels, mais à ma connaissance, il leur manque soit l'une des fonctionnalités fondamentales que j'attendrais des constantes (comme être constante ou être de type arbitraire), soit elles ont des fonctionnalités ésotériques ajoutées qui les rendre moins généralement applicables. Mais YMMV, je serais reconnaissant pour vos commentaires. :-)
la source
def enum(**enums): return type('Enum', (), enums)
.Numbers = enum(ONE=1, TWO=2, THREE='three')
, selon stackoverflow.com/a/1695250/199364 , section "Dans les versions antérieures ..."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:
Vous pouvez consulter un article que j'ai écrit pour trouver plus de façons d'utiliser les propriétés Python.
la source
Edit: Ajout d'un exemple de code pour Python 3
Remarque: cette autre réponse semble fournir une implémentation beaucoup plus complète similaire à la suivante (avec plus de fonctionnalités).
Commencez par créer une métaclasse :
Cela empêche les propriétés statiques d'être modifiées. Créez ensuite une autre classe qui utilise cette métaclasse:
Ou, si vous utilisez Python 3:
Cela devrait empêcher la modification des accessoires d'instance. Pour l'utiliser, héritez:
Maintenant, les accessoires, accessibles directement ou via une instance, doivent être constants:
Voici un exemple de ci-dessus en action. Voici un autre exemple pour Python 3.
la source
Vous pouvez utiliser un tuple nommé comme solution de contournement pour créer efficacement une constante qui fonctionne de la même manière qu'une variable finale statique en Java (une "constante" Java). Comme solutions de contournement, c'est un peu élégant. (Une approche plus élégante consisterait simplement à améliorer le langage Python --- quel type de langage vous permet de redéfinir
math.pi
? - mais je m'égare.)(Au moment où j'écris ceci, je réalise une autre réponse à cette question mentionnée namedtuple, mais je vais continuer ici parce que je vais montrer une syntaxe qui correspond plus étroitement à ce que vous attendez en Java, car il n'est pas nécessaire de créer un nommé tapez comme nommétuple vous oblige à le faire.)
En suivant votre exemple, vous vous souviendrez qu'en Java, nous devons définir la constante à l' intérieur d'une classe ; parce que vous n'avez pas mentionné de nom de classe, appelons-le
Foo
. Voici la classe Java:Voici l'équivalent Python.
Le point clé que je veux ajouter ici est que vous n'avez pas besoin d'un
Foo
type séparé (un "tuple nommé anonyme" serait bien, même si cela ressemble à un oxymore), donc nous nommons notre nommé tuple_Foo
pour que, espérons-le, il ne le soit pas échapper à l'importation de modules.Le deuxième point ici est que nous créons immédiatement une instance du nametuple, en l'appelant
Foo
; il n'est pas nécessaire de le faire dans une étape distincte (sauf si vous le souhaitez). Vous pouvez maintenant faire ce que vous pouvez faire en Java:Mais vous ne pouvez pas lui attribuer:
Remerciements: je pensais avoir inventé l'approche nommée tuple, mais je vois que quelqu'un d'autre a donné une réponse similaire (bien que moins compacte). Ensuite, j'ai également remarqué Que sont les "tuples nommés" en Python? , qui souligne qu'il
sys.version_info
s'agit désormais d'un tuple nommé, donc peut-être que la bibliothèque standard Python a déjà proposé cette idée beaucoup plus tôt.Notez que malheureusement (ceci étant toujours Python), vous pouvez effacer la totalité de l'
Foo
affectation:(facepalm)
Mais au moins, nous empêchons la
Foo.CONST_NAME
valeur d'être modifiée, et c'est mieux que rien. Bonne chance.la source
PEP 591 a le qualificatif «final». L'application est au vérificateur de type.
Vous pouvez donc faire:
Remarque: le
Final
mot-clé s'applique uniquement à la version Python 3.8la source
Voici une implémentation d'une classe "Constantes", qui crée des instances avec des attributs en lecture seule (constants). Par exemple, vous pouvez utiliser
Nums.PI
pour obtenir une valeur qui a été initialisée en tant que3.14159
, etNums.PI = 22
déclenche une exception.Merci à FrozenDict de @MikeGraham , que j'ai utilisé comme point de départ. Modifié, donc au lieu de
Nums['ONE']
la syntaxe d'utilisation estNums.ONE
.Et grâce à la réponse de @ Raufio, pour l'idée de remplacer __ setattr __.
Ou pour une implémentation avec plus de fonctionnalités, consultez les nommé_constants de @Hans_meine sur GitHub
la source
Nums._d['PI'] = 22
Le langage lui-même ne fournit aucun moyen de marquer les choses comme non mutables, je crois.Un tuple est techniquement considéré comme une constante, car un tuple génère une erreur si vous essayez de modifier l'une de ses valeurs. Si vous souhaitez déclarer un tuple avec une valeur, placez une virgule après sa seule valeur, comme ceci:
Pour vérifier la valeur de cette variable, utilisez quelque chose de similaire à ceci:
Si vous essayez de modifier cette valeur, une erreur sera générée.
la source
Je voudrais créer une classe qui remplace la
__setattr__
méthode de la classe d'objet de base et envelopper mes constantes avec cela, notez que j'utilise python 2.7:Pour encapsuler une chaîne:
C'est assez simple, mais si vous souhaitez utiliser vos constantes de la même manière qu'un objet non constant (sans utiliser constObj.value), ce sera un peu plus intensif. Il est possible que cela cause des problèmes, il est donc préférable de garder le
.value
pour afficher et de savoir que vous effectuez des opérations avec des constantes (peut-être pas la manière la plus «pythonique»).la source
def ONE(): return 1
est plus facile à utiliserONE()
que cette réponseONE.value
.Malheureusement, le Python n'a pas encore de constantes et c'est dommage. ES6 a déjà ajouté des constantes de prise en charge à JavaScript ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ) car c'est une chose très utile dans n'importe quel langage de programmation. Comme indiqué dans d'autres réponses de la communauté Python, utilisez la variable majuscule convention - utilisateur comme constantes, mais elle ne protège pas contre les erreurs arbitraires dans le code. Si vous le souhaitez, une solution à fichier unique peut vous être utile dans la suite (voir docstrings comment l'utiliser).
fichier constants.py
Si cela ne suffit pas, consultez le test complet pour cela.
Avantages: 1. Accès à toutes les constantes pour l'ensemble du projet 2. Contrôle strict des valeurs des constantes
Manque: 1. Pas de support pour les types personnalisés et le type «dict»
Remarques:
Testé avec Python3.4 et Python3.5 (j'utilise le 'tox' pour cela)
Environnement de test:
.
la source
La manière pythonique de déclarer des "constantes" est fondamentalement une variable de niveau module:
Et puis écrivez vos classes ou fonctions. Étant donné que les constantes sont presque toujours des entiers et qu'elles sont également immuables en Python, vous avez très peu de chances de le modifier.
Sauf, bien sûr, si vous définissez explicitement
RED = 2
.la source
RED = 2
" est tout l'avantage (dans d'autres langues) de pouvoir déclarer un nom de variable "constant"!static
avoir un seul stockage pour la valeur de toutes les instances d'une classe? Sauf s'il existe une possibilité de déclarer une variable statique / classe.Nous pouvons créer un objet descripteur.
1) Si nous voulions travailler avec des constantes au niveau de l'instance, alors:
2) si nous voulions créer des constantes uniquement au niveau de la classe, nous pourrions utiliser une métaclasse qui sert de conteneur pour nos constantes (nos objets descripteurs); toutes les classes qui descendent hériteront de nos constantes (nos objets descripteurs) sans aucun risque modifiable.
Si je crée une sous-classe de Foo, cette classe héritera de la constante sans possibilité de les modifier
la source
Les dictionnaires Python sont modifiables, ils ne semblent donc pas être un bon moyen de déclarer des constantes:
la source
Voici une astuce si vous voulez des constantes et que vous ne vous souciez pas de leurs valeurs:
Définissez simplement des classes vides.
par exemple:
la source
En python, une constante est simplement une variable avec un nom dans toutes les capitales, avec des mots séparés par le caractère de soulignement,
par exemple
DAYS_IN_WEEK = 7
La valeur est modifiable, car vous pouvez la modifier. Mais étant donné que les règles du nom vous disent que c'est une constante, pourquoi le feriez-vous? Je veux dire, c'est votre programme après tout!
C'est l'approche adoptée tout au long de python. Il n'y a pas de
private
mot-clé pour la même raison. Préfixez le nom avec un trait de soulignement et vous savez qu'il est destiné à être privé. Le code peut enfreindre la règle ... tout comme un programmeur pourrait de toute façon supprimer le mot-clé privé.Python aurait pu ajouter un
const
mot - clé ... mais un programmeur pourrait supprimer le mot-clé puis changer la constante s'il le souhaite, mais pourquoi faire cela? Si vous souhaitez enfreindre la règle, vous pouvez quand même la modifier. Mais pourquoi s'embêter à enfreindre la règle si le nom rend l'intention claire?Peut-être y a-t-il un test unitaire où il est logique d'appliquer une modification à la valeur? Pour voir ce qui se passe pendant une semaine de 8 jours même si dans le monde réel le nombre de jours de la semaine ne peut pas être changé. Si la langue vous empêchait de faire une exception s'il n'y a qu'un seul cas, vous devez enfreindre la règle ... vous devrez alors arrêter de la déclarer comme constante, même si c'est toujours une constante dans l'application, et il y a juste ce cas de test unique qui voit ce qui se passe s'il est modifié.
Le nom tout en majuscule vous indique qu'il est destiné à être une constante. Voilà ce qui est important. Ce n'est pas un langage qui force les contraintes sur le code que vous avez le pouvoir de changer de toute façon.
Telle est la philosophie du python.
la source
Il n'y a pas de moyen parfait de le faire. Si je comprends bien, la plupart des programmeurs capitaliseront simplement l'identifiant, donc PI = 3.142 peut facilement être compris comme une constante.
D'un autre côté, si vous voulez quelque chose qui agit réellement comme une constante, je ne suis pas sûr que vous le trouverez. Avec tout ce que vous faites, il y aura toujours un moyen de modifier la "constante", donc ce ne sera pas vraiment une constante. Voici un exemple très simple et sale:
On dirait que cela fera une constante de style PHP.
En réalité, il suffit à quelqu'un de modifier la valeur:
C'est la même chose pour toutes les autres solutions que vous trouverez ici - même les plus intelligentes qui créent une classe et redéfinissent la méthode d'attribut set - il y aura toujours un moyen de les contourner. C'est comme ça que Python est.
Ma recommandation est d'éviter simplement les tracas et de simplement capitaliser vos identifiants. Ce ne serait pas vraiment une constante appropriée, mais là encore, rien ne le serait.
la source
Il existe un moyen plus propre de le faire avec namedtuple:
Exemple d'utilisation
Avec cette approche exacte, vous pouvez nommer vos constantes.
la source
Peut-être que la bibliothèque pconst vous aidera ( github ).
$ pip install pconst
[Out] Constant value of "APPLE_PRICE" is not editable.
la source
Vous pouvez utiliser StringVar ou IntVar, etc., votre constante est const_val
la source
Vous pouvez le faire avec
collections.namedtuple
etitertools
:la source
(Ce paragraphe était censé être un commentaire sur ces réponses ici et là , qui mentionnaient
namedtuple
, mais il devient trop long pour être intégré dans un commentaire, alors, c'est parti.)L'approche nommée double mentionnée ci-dessus est définitivement innovante. Par souci d'exhaustivité, cependant, à la fin de la section NamedTuple de sa documentation officielle , il se lit comme suit:
En d'autres termes, la documentation officielle préfère utiliser une manière pratique, plutôt que d'implémenter réellement le comportement en lecture seule. Je suppose que cela devient encore un autre exemple de Zen of Python :
la source
Voici une collection d'expressions idiomatiques que j'ai créées pour tenter d'améliorer certaines des réponses déjà disponibles.
Je sais que l'utilisation de constant n'est pas pythonique, et vous ne devriez pas le faire à la maison!
Cependant, Python est un langage tellement dynamique! Ce forum montre comment il est possible de créer des constructions qui ressemblent et se sentent comme des constantes. Cette réponse a pour objectif principal d'explorer ce qui peut être exprimé par la langue.
S'il vous plaît ne soyez pas trop dur avec moi :-).
Pour plus de détails, j'ai écrit un blog d'accompagnement sur ces idiomes .
Dans cet article, j'appellerai une variable constante une référence constante à des valeurs (immuables ou non). De plus, je dis qu'une variable a une valeur figée lorsqu'elle fait référence à un objet mutable qu'un code client ne peut pas mettre à jour sa ou ses valeurs.
Un espace de constantes (SpaceConstants)
Cet idiome crée ce qui ressemble à un espace de noms de variables constantes (aka SpaceConstants). Il s'agit d'une modification d'un extrait de code par Alex Martelli pour éviter l'utilisation d'objets de module. En particulier, cette modification utilise ce que j'appelle une fabrique de classes car dans la fonction SpaceConstants , une classe appelée SpaceConstants est définie et une instance de celle-ci est renvoyée.
J'ai exploré l'utilisation de la fabrique de classes pour implémenter une conception basée sur des politiques en Python dans stackoverflow et également dans un blogpost .
Un espace de valeurs figées (SpaceFrozenValues)
Ce prochain idiome est une modification des SpaceConstants dans laquelle les objets mutables référencés sont figés. Cette implémentation exploite ce que j'appelle la fermeture partagée entre les fonctions setattr et getattr . La valeur de l'objet mutable est copiée et référencée par le cache variable défini à l'intérieur de la fonction de fermeture partagée. Il forme ce que j'appelle une copie protégée contre la fermeture d'un objet mutable .
Vous devez être prudent lorsque vous utilisez cet idiome, car getattr renvoie la valeur du cache en effectuant une copie complète . Cette opération pourrait avoir un impact significatif sur les performances des gros objets!
Un espace constant (ConstantSpace)
Cet idiome est un espace de noms immuable de variables constantes ou ConstantSpace . C'est une combinaison de la réponse incroyablement simple de Jon Betts dans stackoverflow avec une usine de classe .
Un espace figé (FrozenSpace)
Cet idiome est un espace de noms immuable de variables figées ou FrozenSpace . Il est dérivé du modèle précédent en faisant de chaque variable un propriété protégée par la fermeture de la classe FrozenSpace générée .
la source
En Python, les constantes n'existent pas, mais vous pouvez indiquer qu'une variable est une constante et ne doit pas être modifiée en ajoutant
CONST_
au début du nom de la variable et en déclarant qu'il s'agit d'une constante dans un commentaire:Alternativement, vous pouvez créer une fonction qui agit comme une constante:
la source
Dans mon cas, j'avais besoin de tableaux de bord immuables pour une implémentation d'une bibliothèque de crypto contenant de nombreux nombres littéraux que je voulais assurer étaient constants.
Cette réponse fonctionne mais la tentative de réaffectation des éléments bytearray ne génère pas d'erreur.
Les constantes sont immuables, mais l'affectation constante du tableau secondaire échoue silencieusement:
Une approche plus puissante, simple et peut-être encore plus «pythonique» implique l'utilisation d'objets memoryview (objets tampons dans <= python-2.6).
L'affectation d'élément ConstArray est
TypeError
:la source
J'écris une librairie util pour python const: kkconst - pypi support str, int, float, datetime
l'instance de champ const conservera son comportement de type de base.
Par exemple:
plus de détails sur l'utilisation vous pouvez lire l'url pypi : pypi ou github
la source
Vous pouvez encapsuler une constante dans un tableau numpy, la marquer en écriture seule et toujours l'appeler par index zéro.
bien sûr, cela ne protège que le contenu du numpy, pas la variable "CONSTANT" elle-même; vous pouvez toujours faire:
et
CONSTANT
changerait, mais cela déclencherait rapidement une TypeError la première foisCONSTANT[0]
est appelée plus tard dans le script.bien que ... je suppose que si vous avez changé à un moment donné
maintenant, vous n'obtiendrez plus le TypeError. hmmmm ....
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html
la source