Come posso verificare se esiste una variabile?


954

Voglio verificare se esiste una variabile. Ora sto facendo qualcosa del genere:

try:
   myVar
except NameError:
   # Do something.

Ci sono altri modi senza eccezioni?


15
Cosa c'è di sbagliato nell'eccezione?
S.Lott

10
@ S.Lott: se myVarqualcosa è davvero complicato, che richiede molto tempo per produrre / valutare, le trycose non rallenterebbero?
dbliss,

3
@dbliss: è una variabile. A parte alcuni casi davvero strani se stai facendo qualcosa di folle execo metaclassi, non sarà costoso.
user2357112 supporta Monica

Una più completa risposta: stackoverflow.com/a/1592578/1661797
nickboldt

Risposte:


1628

Per verificare l'esistenza di una variabile locale:

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

Per verificare l'esistenza di una variabile globale:

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

Per verificare se un oggetto ha un attributo:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.

30
Ok, e come posso controllare l'attributo esistente in classe?
Max Frai,

7
e come si trasforma il nome della variabile che forse non esiste in una stringa?
SilentGhost,

15
Ma l'OP sta digitando il codice, possono digitare 'myVar' all'interno di myVar. Se il nome della variabile non è noto durante la scrittura del codice, verrà archiviato in una variabile di stringa in fase di esecuzione e anche il controllo che ho pubblicato funzionerà.
Ayman Hourieh,

8
Esistono anche variabili incorporate e, se si dispone di funzioni nidificate, variabili in ambiti esterni. Se vuoi controllarli tutti, probabilmente è meglio innescare NameErrordopo tutto.
Petr Viktorin,

14
Mi è piaciuto migliore if hasattr(obj, 'attr_name'):che funziona per le classi troppo: vale a direif hasattr(self, 'attr_name'):
Ron Kalian

118

L' uso di variabili che devono ancora essere definite o impostate (implicitamente o esplicitamente) è quasi sempre una cosa negativa in qualsiasi lingua, dal momento che spesso indica che la logica del programma non è stata pensata correttamente e probabilmente risulterà in un comportamento imprevedibile.

Se avete bisogno di farlo in Python, il seguente trucco, che è simile al vostro, farà in modo che una variabile ha un certo valore prima dell'uso:

try:
    myVar
except NameError:
    myVar = None

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

Tuttavia, non sono ancora convinto che sia una buona idea - a mio avviso, dovresti provare a riformattare il tuo codice in modo che questa situazione non si verifichi.


8
Forse è una variabile di una dipendenza, e secondo la versione / piattaforma potrebbe esistere o non esistere, e non c'è altro modo di sapere quale versione sia.
WhyNotHugo,

35
Le variabili di stato non esistono prima che vengano assegnate: se si disegna una linea dalla posizione precedente alla posizione corrente, quindi si imposta precedente = corrente, non significa che "non si conoscono le variabili" alla prima chiamata. E scrivere una riga aggiuntiva di codice per inizializzare precedente = null al di fuori della routine di disegno non significa che "conosci meglio le tue variabili".
Dave,

4
Il mio punto è che un blocco "if last: draw (last, current); last = current" è facile da capire e non è una programmazione scadente. L'aggiunta di un "prova / tranne" per verificare l'esistenza di "ultimo" prima di poterlo testare riduce la leggibilità di quel codice.
Dave,

23
"L'uso di variabili che non sono state definite è in realtà una cosa negativa in qualsiasi lingua" Risparmiami il discorso condiscendente. Alcuni di noi usano Python per semplici script matematici o statistici usando IDE come Spyder che funzionano come Matlab. A volte ha senso in quegli ambienti consentire all'utente di definire le variabili nella console globale e verificare altrimenti se non sono dichiarate nello script come quando si fa matematica in Matlab.
Ricardo Cruz,

15
@Ricardo, forse, piuttosto che assumere la sua condiscendenza, potresti voler considerare almeno la possibilità che sia solo un buon consiglio da qualcuno che potrebbe essere più informato :-) O lo considereresti altrettanto condiscendente se ti sconsigliassi di un uso non vincolato del globale variabili, spaghetti code, oggetti god, rilascio di codice non testato o scrittura di sistemi operativi in ​​COBOL? La mia risposta affermava perché pensavo che fosse una cattiva idea (e non c'era nulla nella domanda che indicasse perché OP pensasse che fosse necessario), ma forniva comunque un modo per la possibilità che volessero davvero farlo.
paxdiablo,

53

Un modo semplice è inizializzarlo a prima vista myVar = None

Più tardi:

if myVar is not None:
    # Do something

2
C'è molto da migliorare in questa risposta. Piuttosto - Un modo semplice è dichiararlo per primo. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan

mi piace molto perché ho impostato le cose su Nessuno nelle mie exceptdichiarazioni
HashRocketSyntax

perché non qualcosa del genere: if myVar: # Do something questo evita la necessità di leggere un doppio negativo
jjisnow

@jjisnow Perché vuoi che questa condizione sia vera anche se myVarè un elenco vuoto, zero, stringa vuota ecc.
Gabriel,

7
@jjisnow if myVar: # Do somethinglancia NameErrorin python3 se myVar non viene dichiarato
Agile Bean

25

L'uso di try / exception è il modo migliore per verificare l'esistenza di una variabile. Ma c'è quasi sicuramente un modo migliore di fare qualunque cosa tu stia facendo che impostare / testare variabili globali.

Ad esempio, se vuoi inizializzare una variabile a livello di modulo la prima volta che chiami una funzione, stai meglio con un codice simile a questo:

my_variable = None

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

2
Cerco di non usarlo, perché inquina lo spazio dei nomi globale. Un modo per evitarlo è rendere la funzione una classe, con my_variable come variabile di classe, e definire call come il corpo della funzione esistente, ma è una seccatura da programmare e apre una serie di altre domande. Preferisco usare gli attributi di funzione, vedi sotto.
Samwyse,

17

per oggetti / moduli, puoi anche

'var' in dir(obj)

Per esempio,

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

11

Presumo che il test verrà utilizzato in una funzione, simile alla risposta di user97370 . Non mi piace quella risposta perché inquina lo spazio dei nomi globale. Un modo per risolverlo è utilizzare invece una classe:

class InitMyVariable(object):
  my_variable = None

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

Non mi piace, perché complica il codice e apre domande come, questo dovrebbe confermare al modello di programmazione di Singleton? Fortunatamente, Python ha permesso alle funzioni di avere degli attributi per un po ', il che ci offre questa semplice soluzione:

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

9

catchviene chiamato exceptin Python. a parte questo va bene per casi così semplici. C'è quello AttributeErrorche può essere usato per verificare se un oggetto ha un attributo.


5

Un modo che spesso funziona bene per gestire questo tipo di situazione è non controllare esplicitamente se la variabile esiste ma andare avanti e concludere il primo utilizzo della variabile eventualmente inesistente in un try / tranne 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
  ...

3

Ho creato una funzione personalizzata.

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

Quindi la chiamata come segue sostituisce variable_namecon la variabile che si desidera verificare:

exists("variable_name")

Tornerà TrueoFalse


2
No, questo non funzionerà. locals()è ... err ... locale alla funzione exists😅
bgusach

1
1) La funzione locals () è locale. 2) Perché l'assegnazione extra di var_exists?
Dave,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.