Wie überprüfe ich, ob eine Variable vorhanden ist?

954

Ich möchte überprüfen, ob eine Variable existiert. Jetzt mache ich so etwas:

try:
   myVar
except NameError:
   # Do something.

Gibt es andere Möglichkeiten ohne Ausnahmen?

Max Frai
quelle
15
Was ist los mit der Ausnahme?
S.Lott
10
@ S.Lott: Wenn myVaretwas wirklich kompliziert ist, dessen Produktion / Bewertung lange dauert, würden sich die tryDinge dann nicht verlangsamen?
Dbliss
3
@dbliss: Es ist eine Variable. Abgesehen von einigen wirklich seltsamen Fällen, wenn Sie etwas Verrücktes mit execMetaklassen machen, wird es nicht teuer.
user2357112 unterstützt Monica
Eine vollständigere Antwort: stackoverflow.com/a/1592578/1661797
nickboldt

Antworten:

1628

So überprüfen Sie die Existenz einer lokalen Variablen:

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

So überprüfen Sie die Existenz einer globalen Variablen:

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

So überprüfen Sie, ob ein Objekt ein Attribut hat:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
quelle
29
Ok, und wie kann ich das in der Klasse vorhandene Attribut überprüfen?
Max Frai
7
und wie wandelt man den Namen einer Variablen, die möglicherweise nicht existiert, in einen String um?
SilentGhost
15
Aber das OP gibt den Code ein, sie können 'myVar' anstelle von myVar eingeben. Wenn der Variablenname beim Schreiben des Codes nicht bekannt ist, wird er zur Laufzeit in einer Zeichenfolgenvariablen gespeichert, und die von mir veröffentlichte Prüfung funktioniert auch.
Ayman Hourieh
8
Es gibt auch integrierte Variablen und, wenn Sie verschachtelte Funktionen haben, Variablen in äußeren Bereichen. Wenn Sie nach allen suchen möchten, ist es wahrscheinlich am besten, wenn Sie doch auslösen NameError.
Petr Viktorin
14
Mir hat am besten gefallen, if hasattr(obj, 'attr_name'):was auch für Klassen funktioniert: dhif hasattr(self, 'attr_name'):
Ron Kalian
118

Die Verwendung von Variablen, die noch definiert oder festgelegt wurden (implizit oder explizit), ist in jeder Sprache fast immer eine schlechte Sache , da dies häufig darauf hinweist, dass die Logik des Programms nicht richtig durchdacht wurde und wahrscheinlich resultiert in unvorhersehbarem Verhalten.

Wenn Sie brauchen es in Python zu tun, die folgenden Trick, die ähnlich wie bei Ihnen ist, wird sichergestellt , dass eine Variable hat einige Wert vor der Verwendung:

try:
    myVar
except NameError:
    myVar = None

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

Ich bin jedoch immer noch nicht davon überzeugt, dass dies eine gute Idee ist. Meiner Meinung nach sollten Sie versuchen, Ihren Code so umzugestalten, dass diese Situation nicht auftritt.

paxdiablo
quelle
8
Vielleicht ist es eine Variable einer Abhängigkeit, und je nach Version / Plattform kann es existieren oder nicht, und es gibt keine andere Möglichkeit zu wissen, um welche Version es sich handelt.
WhyNotHugo
35
Statusvariablen existieren nicht, bevor sie zugewiesen werden. Wenn Sie eine Linie von der vorherigen Position zur aktuellen Position ziehen und dann previous = current setzen, bedeutet dies nicht, dass Sie beim ersten Aufruf "Ihre Variablen nicht kennen". Das Schreiben einer zusätzlichen Codezeile zum Initialisieren von previous = null außerhalb der Zeichenroutine bedeutet nicht, dass Sie Ihre Variablen besser kennen.
Dave
4
Mein Punkt ist, dass ein Block "if last: draw (last, current); last = current" leicht zu verstehen ist und keine schlechte Programmierung. Das Hinzufügen eines "try / Except", um zu prüfen, ob "last" vorhanden ist, bevor es getestet werden kann, beeinträchtigt die Lesbarkeit dieses Codes.
Dave
23
"Die Verwendung von Variablen, die nicht definiert wurden, ist in jeder Sprache eine schlechte Sache." Ersparen Sie mir die herablassende Rede. Einige von uns verwenden Python für einfache Mathematik- oder Statistikskripte mit IDEs wie Spyder, die wie Matlab funktionieren. In solchen Umgebungen ist es manchmal sinnvoll, dem Benutzer zu erlauben, Variablen in der globalen Konsole zu definieren und anderweitig zu prüfen, ob sie im Skript nicht deklariert sind, wie dies bei der Mathematik in Matlab der Fall ist.
Ricardo Cruz
15
@Ricardo vielleicht eher als Herablassung unter der Annahme, dass Sie zumindest wollen betrachten die Möglichkeit , dass es nur gute Ratschläge von jemandem, der kann mehr Wissen sein :-) Oder würden Sie es für ebenso gönnerhaft , wenn ich gegen eine unbeschränkte Nutzung globaler empfohlen Variablen, Spaghetti-Code, Gott-Objekte, Veröffentlichung von nicht getestetem Code oder Schreiben von Betriebssystemen in COBOL? In meiner Antwort stand, warum ich es für eine schlechte Idee hielt (und es gab nichts in der Frage, warum OP dies für notwendig hielt), aber dennoch einen Weg für die Möglichkeit darstellte, dass sie es wirklich wollten.
Paxdiablo
52

Eine einfache Möglichkeit besteht darin, es auf den ersten Blick zu initialisieren myVar = None

Dann später:

if myVar is not None:
    # Do something
Chinedum Ukejianya
quelle
2
In dieser Antwort gibt es viel zu verbessern. Eher - Ein einfacher Weg ist es, es zuerst zu deklarieren. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan
Ich mag dieses sehr, weil ich Dinge in meinen exceptAussagen auf Keine gesetzt habe
HashRocketSyntax
warum nicht so etwas wie: if myVar: # Do something Dies vermeidet die Notwendigkeit, ein doppeltes Negativ zu lesen
jjisnow
@jjisnow Weil Sie möchten, dass diese Bedingung erfüllt ist, auch wenn myVares sich um eine leere Liste, Null, eine leere Zeichenfolge usw. handelt
Gabriel
7
@jjisnow if myVar: # Do somethingwirft NameErrorin Python3, wenn myVar nicht deklariert ist
Agile Bean
25

Die Verwendung von try / Except ist der beste Weg, um die Existenz einer Variablen zu testen. Aber es gibt mit ziemlicher Sicherheit eine bessere Möglichkeit, das zu tun, was Sie gerade tun, als globale Variablen festzulegen / zu testen.

Wenn Sie beispielsweise beim ersten Aufrufen einer Funktion eine Variable auf Modulebene initialisieren möchten, sollten Sie folgenden Code verwenden:

my_variable = None

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

quelle
2
Ich versuche dies nicht zu verwenden, da es den globalen Namespace verschmutzt. Eine Möglichkeit, dies zu vermeiden, besteht darin, die Funktion zu einer Klasse mit my_variable als Klassenvariable zu machen und den Aufruf als Hauptteil der vorhandenen Funktion zu definieren. Dies ist jedoch schwierig zu codieren und wirft eine Reihe anderer Fragen auf. Ich bevorzuge die Verwendung von Funktionsattributen, siehe unten.
Samwyse
17

für Objekte / Module können Sie auch

'var' in dir(obj)

Zum Beispiel,

>>> class Something(object):
...     pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
Wyrmwood
quelle
11

Ich gehe davon aus, dass der Test in einer Funktion verwendet wird, ähnlich der Antwort von user97370 . Diese Antwort gefällt mir nicht, weil sie den globalen Namespace verschmutzt. Eine Möglichkeit, dies zu beheben, besteht darin, stattdessen eine Klasse zu verwenden:

class InitMyVariable(object):
  my_variable = None

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

Ich mag das nicht, weil es den Code kompliziert und Fragen aufwirft, wie sollte dies das Singleton-Programmiermuster bestätigen? Glücklicherweise hat Python Funktionen für eine Weile erlaubt, Attribute zu haben, was uns diese einfache Lösung gibt:

def InitMyVariable():
  if InitMyVariable.my_variable is None:
    InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
Samwyse
quelle
9

catchwird exceptin Python aufgerufen . Ansonsten ist es in Ordnung für so einfache Fälle. Mit AttributeErrordieser Option können Sie überprüfen, ob ein Objekt ein Attribut hat.

SilentGhost
quelle
5

Eine Möglichkeit, die häufig gut für den Umgang mit dieser Art von Situation geeignet ist, besteht darin, nicht explizit zu überprüfen, ob die Variable vorhanden ist, sondern nur die erste Verwendung der möglicherweise nicht vorhandenen Variablen in einen Versuch / außer NameError einzuschließen:

# 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
quelle
3

Ich habe eine benutzerdefinierte Funktion erstellt.

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

Rufen Sie dann die folgende Funktion auf und ersetzen Sie sie variable_namedurch die Variable, die Sie überprüfen möchten:

exists("variable_name")

Komme zurück TrueoderFalse

Abhishek R.
quelle
2
Nein, das wird nicht funktionieren. locals()ist ... äh ... lokal für die Funktion exists😅
bgusach
1
1) Die Funktion local () ist lokal. 2) Warum besteht die zusätzliche Zuweisung von var_exists?
Dave