Comment vérifier si une variable existe?

955

Je veux vérifier si une variable existe. Maintenant, je fais quelque chose comme ça:

try:
   myVar
except NameError:
   # Do something.

Existe-t-il d'autres moyens sans exception?

Max Frai
la source
15
Quel est le problème avec l'exception?
S.Lott
10
@ S.Lott: si myVarquelque chose est vraiment compliqué, qui prend beaucoup de temps à produire / évaluer, les trychoses ne ralentiraient-elles pas?
dbliss
3
@dbliss: C'est une variable. Mis à part certains cas vraiment étranges, si vous faites quelque chose de fou avec des execmétaclasses, cela ne va pas coûter cher.
user2357112 prend en charge Monica
Une réponse plus complète: stackoverflow.com/a/1592578/1661797
nickboldt

Réponses:

1629

Pour vérifier l'existence d'une variable locale:

if 'myVar' in locals():
  # myVar exists.

Pour vérifier l'existence d'une variable globale:

if 'myVar' in globals():
  # myVar exists.

Pour vérifier si un objet a un attribut:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
la source
31
Ok, et comment puis-je vérifier l'attribut existant en classe?
Max Frai
7
et comment transformer le nom d'une variable qui n'existe peut-être pas en chaîne?
SilentGhost
15
Mais l'OP tape le code, ils peuvent taper 'myVar' au lieu de myVar. Si le nom de la variable n'est pas connu lorsque le code est écrit, il sera stocké dans une variable de chaîne lors de l'exécution, et la vérification que j'ai publiée fonctionnera également.
Ayman Hourieh,
8
Il existe également des variables intégrées et, si vous avez des fonctions imbriquées, des variables dans les étendues externes. Si vous voulez les vérifier tous, vous feriez probablement mieux de déclencher NameErroraprès tout.
Petr Viktorin
14
J'ai préféré if hasattr(obj, 'attr_name'):ce qui fonctionne aussi pour les cours: ieif hasattr(self, 'attr_name'):
Ron Kalian
118

L' utilisation de variables qui n'ont pas encore été définies ou définies (implicitement ou explicitement) est presque toujours une mauvaise chose dans n'importe quelle langue, car elle indique souvent que la logique du programme n'a pas été bien réfléchie et est susceptible de résulter dans un comportement imprévisible.

Si vous devez le faire en Python, l'astuce suivante, similaire à la vôtre, garantira qu'une variable a une certaine valeur avant utilisation:

try:
    myVar
except NameError:
    myVar = None

# Now you're free to use myVar without Python complaining.

Cependant, je ne suis toujours pas convaincu que c'est une bonne idée - à mon avis, vous devriez essayer de refactoriser votre code afin que cette situation ne se produise pas.

paxdiablo
la source
8
Peut-être que c'est une variable d'une dépendance, et selon la version / plate-forme, elle peut ou non exister, et il n'y a pas d'autre moyen de savoir de quelle version il s'agit.
WhyNotHugo
35
Les variables d'état n'existent pas avant leur affectation - si vous tracez une ligne de la position précédente à la position actuelle, puis définissez previous = current, cela ne signifie pas que vous "ne connaissez pas vos variables" lors du premier appel. Et écrire une ligne de code supplémentaire pour initialiser previous = null en dehors de la routine de dessin ne signifie pas que vous "connaissez mieux vos variables".
Dave
4
Mon point est qu'un bloc "if last: draw (last, current); last = current" est facile à comprendre et n'est pas une mauvaise programmation. L'ajout d'un "try / except" pour vérifier l'existence de "last" avant de pouvoir le tester nuit à la lisibilité de ce code.
Dave
23
"L'utilisation de variables qui n'ont pas été définies est en fait une mauvaise chose dans n'importe quelle langue" Épargnez-moi le discours condescendant. Certains d'entre nous utilisent Python pour des scripts mathématiques ou statistiques simples utilisant des IDE tels que Spyder qui fonctionnent comme Matlab. Il est parfois judicieux dans ces environnements de permettre à l'utilisateur de définir des variables dans la console globale et de vérifier autrement si elles ne sont pas déclarées dans le script comme lors des mathématiques dans Matlab.
Ricardo Cruz
15
@Ricardo, peut-être, plutôt que de supposer que c'est de la condescendance, vous voudrez peut-être au moins envisager la possibilité que ce soit juste de bons conseils de quelqu'un qui pourrait être plus compétent :-) Ou considéreriez-vous tout aussi condescendant si je déconseillais l'utilisation non contrainte de global de variables, de code spaghetti, d'objets divins, de libérer du code non testé ou d'écrire des systèmes d'exploitation dans COBOL? Ma réponse a expliqué pourquoi je pensais que c'était une mauvaise idée (et rien dans la question n'indiquait pourquoi OP pensait que c'était nécessaire) mais a quand même fourni un moyen sur la chance qu'ils voulaient vraiment le faire.
paxdiablo
53

Un moyen simple est de l'initialiser en disant d'abord myVar = None

Plus tard:

if myVar is not None:
    # Do something
Chinedum Ukejianya
la source
2
Il y a beaucoup à améliorer dans cette réponse. Plutôt - Un moyen simple consiste à le déclarer en premier. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan
j'aime beaucoup celui-ci parce que j'ai réglé les choses sur None dans mes exceptdéclarations
HashRocketSyntax
pourquoi pas quelque chose comme: if myVar: # Do something Cela évite d'avoir à lire un double négatif
jjisnow
@jjisnow Parce que vous voulez que cette condition soit vraie même s'il myVars'agit d'une liste vide, zéro, chaîne vide, etc.
Gabriel
7
@jjisnow if myVar: # Do somethinglance NameErroren python3 si myVar n'est pas déclaré
Agile Bean
25

L'utilisation de try / except est la meilleure façon de tester l'existence d'une variable. Mais il y a presque certainement une meilleure façon de faire quoi que ce soit que de définir / tester des variables globales.

Par exemple, si vous souhaitez initialiser une variable de niveau module la première fois que vous appelez une fonction, vous feriez mieux de coder quelque chose comme ceci:

my_variable = None

def InitMyVariable():
  global my_variable
  if my_variable is None:
    my_variable = ...

la source
2
J'essaie de ne pas l'utiliser, car cela pollue l'espace de noms global. Une façon d'éviter cela est de faire de la fonction une classe, avec my_variable comme variable de classe, et de définir call comme le corps de la fonction existante, mais c'est pénible à coder et ouvre un tas d'autres questions. Je préfère utiliser les attributs de fonction, voir ci-dessous.
samwyse
17

pour les objets / modules, vous pouvez également

'var' in dir(obj)

Par exemple,

>>> class Something(object):
...     pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
Bois de wyrm
la source
11

Je suppose que le test va être utilisé dans une fonction, similaire à la réponse de user97370 . Je n'aime pas cette réponse car elle pollue l'espace de noms global. Une façon de résoudre ce problème consiste à utiliser une classe à la place:

class InitMyVariable(object):
  my_variable = None

def __call__(self):
  if self.my_variable is None:
   self.my_variable = ...

Je n'aime pas cela, car cela complique le code et ouvre des questions telles que, cela devrait-il confirmer le modèle de programmation Singleton? Heureusement, Python a permis aux fonctions d'avoir des attributs pendant un certain temps, ce qui nous donne cette solution simple:

def InitMyVariable():
  if InitMyVariable.my_variable is None:
    InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
samwyse
la source
9

catchest appelé excepten Python. à part ça, c'est bien pour des cas aussi simples. Il y a le AttributeErrorqui peut être utilisé pour vérifier si un objet a un attribut.

SilentGhost
la source
5

Un moyen qui fonctionne souvent bien pour gérer ce type de situation consiste à ne pas vérifier explicitement si la variable existe, mais à aller de l'avant et à envelopper la première utilisation de la variable éventuellement non existante dans un try / except NameError:

# Search for entry.
for x in y:
  if x == 3:
    found = x

# Work with found entry.
try:
  print('Found: {0}'.format(found))
except NameError:
  print('Not found')
else:
  # Handle rest of Found case here
  ...
Roger Dahl
la source
3

J'ai créé une fonction personnalisée.

def exists(var):
     var_exists = var in locals() or var in globals()
     return var_exists

Ensuite, appelez la fonction comme suit en remplaçant variable_namepar la variable que vous souhaitez vérifier:

exists("variable_name")

Reviendra TrueouFalse

Abhishek R
la source
2
Non, cela ne fonctionnera pas. locals()est ... euh ... local à la fonction exists😅
bgusach
1
1) La fonction locals () est locale. 2) Pourquoi l'affectation supplémentaire de var_exists?
Dave