¿Cómo verifico si existe una variable?

955

Quiero verificar si existe una variable. Ahora estoy haciendo algo como esto:

try:
   myVar
except NameError:
   # Do something.

¿Hay otras formas sin excepciones?

Max Frai
fuente
15
¿Qué pasa con la excepción?
S.Lott
10
@ S.Lott: si myVares algo realmente complicado, que lleva mucho tiempo producir / evaluar, ¿no se tryralentizarían las cosas?
dbliss
3
@dbliss: es una variable. Aparte de algunos casos realmente extraños si estás haciendo algo loco execo metaclases, no será costoso.
user2357112 es compatible con Monica el
Una respuesta más completa: stackoverflow.com/a/1592578/1661797
nickboldt

Respuestas:

1629

Para verificar la existencia de una variable local:

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

Para verificar la existencia de una variable global:

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

Para verificar si un objeto tiene un atributo:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
fuente
31
Ok, ¿y cómo puedo verificar el atributo existente en la clase?
Max Frai
77
¿Y cómo se convierte el nombre de la variable que posiblemente no existe en una cadena?
SilentGhost
15
Pero el OP está escribiendo el código, pueden escribir 'myVar' en lugar de myVar. Si no se conoce el nombre de la variable cuando se escribe el código, se almacenará en una variable de cadena en tiempo de ejecución, y la comprobación que publiqué también funcionará.
Ayman Hourieh
8
También hay variables integradas y, si tiene funciones anidadas, variables en ámbitos externos. Si desea verificarlos todos, probablemente sea mejor que se active NameErrordespués de todo.
Petr Viktorin
14
Me gustó más lo if hasattr(obj, 'attr_name'):que también funciona para las clases: es decirif hasattr(self, 'attr_name'):
Ron Kalian
118

El uso de variables que aún no se han definido o establecido (implícita o explícitamente) es casi siempre algo malo en cualquier lenguaje, ya que a menudo indica que la lógica del programa no se ha pensado correctamente y es probable que resulte en comportamiento impredecible.

Si necesita hacerlo en Python, el siguiente truco, que es similar al suyo, garantizará que una variable tenga algún valor antes de su uso:

try:
    myVar
except NameError:
    myVar = None

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

Sin embargo, todavía no estoy convencido de que sea una buena idea; en mi opinión, debe intentar refactorizar su código para que esta situación no ocurra.

paxdiablo
fuente
8
Tal vez sea una variable de dependencia y, según la versión / plataforma, puede existir o no, y no hay otra forma de saber qué versión es.
WhyNotHugo
35
Las variables de estado no existen antes de que se asignen: si dibuja una línea desde la posición anterior a la posición actual, luego establece anterior = actual, no significa que "no conozca sus variables" en la primera llamada. Y escribir una línea de código adicional para inicializar anterior = nulo fuera de la rutina de dibujo no significa que "conozca sus variables" mejor.
Dave
44
Mi punto es que un bloque "if last: draw (last, current); last = current" es fácil de entender y no es una mala programación. Agregar un "try / except" para verificar la existencia de "last" antes de poder probarlo resta valor a la legibilidad de ese código.
Dave
23
"El uso de variables que no se han definido es realmente algo malo en cualquier idioma". Ahórreme el discurso condescendiente. Algunos de nosotros usamos Python para scripts matemáticos o estadísticos simples usando IDEs como Spyder que funcionan como Matlab. A veces tiene sentido en esos entornos permitir que el usuario defina variables en la consola global y compruebe si no están declaradas en el script, como cuando se hacen matemáticas en Matlab.
Ricardo Cruz
15
@Ricardo, tal vez, en lugar de asumir que la condescendencia, es posible que desee al menos considerar la posibilidad de que es sólo un buen consejo de alguien que puede ser más bien :-) O habría que considerar igualmente condescendiente si me aconsejó contra el uso sin restricciones del mundial variables, código de espagueti, objetos divinos, liberar código no probado o escribir sistemas operativos en COBOL? Mi respuesta indicó por qué pensé que era una mala idea (y no había nada en la pregunta que indicara por qué OP pensó que era necesario), pero aún así proporcionó una oportunidad en caso de que realmente quisieran hacerlo.
paxdiablo
53

Una forma simple es inicializarlo al principio diciendo myVar = None

Luego más tarde:

if myVar is not None:
    # Do something
Chinedum Ukejianya
fuente
2
Hay mucho que mejorar en esta respuesta. Más bien: una forma simple es declararlo primero. myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'
Shawn Mehan
i como éste mucho porque me puse las cosas en Ninguno en mis exceptdeclaraciones
HashRocketSyntax
¿por qué no algo como: if myVar: # Do something Esto evita la necesidad de leer una doble negación
jjisnow
@jjisnow Porque desea que esta condición sea verdadera incluso si myVares una lista vacía, cero, cadena vacía, etc.
Gabriel
77
@jjisnow if myVar: # Do somethinglanza NameErrorpython3 si no se declara myVar
Agile Bean
25

Usar try / except es la mejor manera de probar la existencia de una variable. Pero es casi seguro que hay una mejor manera de hacer lo que sea que esté haciendo que establecer / probar variables globales.

Por ejemplo, si desea inicializar una variable de nivel de módulo la primera vez que llama a alguna función, es mejor que tenga un código como este:

my_variable = None

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

fuente
2
Intento no usar esto, porque contamina el espacio de nombres global. Una forma de evitar esto es hacer que la función sea una clase, con my_variable como una variable de clase, y definir call como el cuerpo de la función existente, pero eso es difícil de codificar y abre muchas otras preguntas. Prefiero usar atributos de función, ver más abajo.
samwyse
17

para objetos / módulos, también puede

'var' in dir(obj)

Por ejemplo,

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

Asumiré que la prueba se usará en una función, similar a la respuesta del usuario 97370 . No me gusta esa respuesta porque contamina el espacio de nombres global. Una forma de solucionarlo es usar una clase en su lugar:

class InitMyVariable(object):
  my_variable = None

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

No me gusta esto, porque complica el código y abre preguntas como, ¿debería esto confirmar el patrón de programación Singleton? Afortunadamente, Python ha permitido que las funciones tengan atributos por un tiempo, lo que nos brinda esta solución simple:

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

catchse llama excepten Python. Aparte de eso, está bien para casos tan simples. Existe el AttributeErrorque se puede usar para verificar si un objeto tiene un atributo.

SilentGhost
fuente
5

Una forma que a menudo funciona bien para manejar este tipo de situación es no verificar explícitamente si la variable existe, sino simplemente continuar y envolver el primer uso de la variable posiblemente no existente en 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
fuente
3

Creé una función personalizada.

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

Luego, la llamada a la función como sigue se reemplaza variable_namecon la variable que desea verificar:

exists("variable_name")

Volverá TrueoFalse

Abhishek R
fuente
2
No, esto no funcionará. locals()es ... err ... local para la función exists😅
bgusach
1
1) La función locals () es local. 2) ¿Por qué la asignación adicional de var_exists?
Dave