1348

I want to check if a variable exists. Now I'm doing something like this:

try:
    myVar
except NameError:
    # Do something.

Are there other ways without exceptions?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Max Frai
  • 61,946
  • 78
  • 197
  • 306
  • 24
    What's wrong with the exception? – S.Lott May 09 '09 at 15:25
  • 15
    @S.Lott: if `myVar` is something really complicated, that takes a long time to produce/evaluate, wouldn't the `try` slow things down? – abcd Apr 09 '15 at 07:01
  • 7
    @dbliss: It's a variable. Aside from some really weird cases if you're doing something crazy with `exec` or metaclasses, it's not going to be expensive. – user2357112 Sep 12 '16 at 16:36
  • 1
    A more complete answer: http://stackoverflow.com/a/1592578/1661797 – nickboldt Sep 29 '16 at 23:15
  • Keep in mind that exceptions per se are very cheap in python, compared to e.g. java and are almost encouraged / pythonic – ntg Oct 02 '21 at 04:43

15 Answers15

2253

To check the existence of a local variable:

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

To check the existence of a global variable:

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

To check if an object has an attribute:

if hasattr(obj, 'attr_name'):
  # obj.attr_name exists.
Ayman Hourieh
  • 132,184
  • 23
  • 144
  • 116
  • 43
    Ok, and how can i check attribute existing in class? – Max Frai May 09 '09 at 13:19
  • 11
    and how do you turn the name of variable that possibly doesn't exist into a string? – SilentGhost May 09 '09 at 13:27
  • @SilentGhost, can you elaborate more or give an example? – Ayman Hourieh May 09 '09 at 13:38
  • 1
    'myVar' is a str, myVar is variable name. OP doesn't seem to have 'myVar'. – SilentGhost May 09 '09 at 13:42
  • 20
    But the OP is typing the code, they can type 'myVar' intstead of myVar. If the variable name is not known when the code is written, it will be stored in a string variable at runtime, and the check I posted will also work. – Ayman Hourieh May 09 '09 at 13:46
  • 10
    There are also built-in variables, and, if you have nested functions, variables in outer scopes. If you want to check for all of them, you're probably best off triggering `NameError` after all. – Petr Viktorin Jun 10 '14 at 20:18
  • Since in Python a `class` itself is an instance , can I check that a variable is present in the class definition. – Krishna Oza Mar 10 '17 at 03:49
  • You should mention that `hasattr` can not reliably tell you whether an attribute exists or not. For example, when the attribute is a property and accessing the property raises an exception, the result from hasattr can be wrong! – wim Mar 25 '17 at 21:23
  • 23
    I liked best `if hasattr(obj, 'attr_name'):` which works for classes too: ie `if hasattr(self, 'attr_name'):` – Ron Kalian Oct 30 '17 at 11:10
  • 1
    Hmm. The processing cost of doing this (looking for a matching string element within an array) in a loop is significant. I'll end up using the try-catch sample below since it has the least processing overhead. – Brad Hein Apr 13 '18 at 15:20
  • 1
    This will not work for unhashable types, like `[] in globals()` – Chris_Rands May 01 '18 at 08:09
  • 2
    Note that from the documentation for [`hasattr`](https://docs.python.org/3.7/library/functions.html#hasattr): "This is implemented by calling `getattr(object, name)` and seeing whether it raises an `AttributeError` or not" - so it may be cleaner code that explicitly catching the exception, but it may not be faster. – zelanix Sep 18 '18 at 13:24
  • @zelanix Good spot. This actually makes `hasattr` buggy by design - if the variable is a property that raises an error - even if indirectly - then, `hasattr` confusingly returns `False`, even though the attribute exists. Classic mistake of forgetting that exceptions propagate and I'm surprised to see it in the Python base code. – c z Dec 09 '20 at 09:05
  • This doesn't work for `display(...)` in a Jupyter notebook. `'display' in locals() or 'display' in globals()` returns False - even though I can use the function. I want to use this to decide which print-function to use for showing a pandas DataFrame. – Tobias Bergkvist Feb 08 '22 at 19:39
179

The use of variables that have yet to been defined or set (implicitly or explicitly) is often a bad thing, since it tends to indicate that the logic of the program hasn't necessarily been thought through completely, and is likely to result in unpredictable behaviour.

If you do need to do it in Python, the following trick, which is similar to yours, will ensure that a variable has some value before use:

try:
    myVar
except NameError:
    myVar = None      # or some other default value.

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

The value you choose to give it will, of course, depend on what you want to do in such a case. For example, it it was a starting value for some accumulator, you would set it to zero.


However (and this is my opinion), it would probably be better to refactor your code so that this situation does not occur.

By way of an example, the following code was given a comment to this answer, to allow line drawing from a previous point to the current point:

if last:
    draw(last, current);
last = current

In the case where last has not been bound to a value, that won't help in Python at all since even the checking of last will raise an exception. A better idea would be to ensure last does have a value, one that can be used to decide whether or not it is valid. That would be something like:

last = None

# some time passes ...

if last is not None:
    draw(last, current);
last = current

That ensures the variable exists and that you only use it if it's valid for what you need it for.

You can still add the code to force this (if you have no control over the initial setting of the variable) by using the exception method given above:

# Variable 'last' may or may not be bound to a value at this point.

try:
    last
except NameError:
    last = None

# It will always now be bound to a value at this point.

if last is not None:
    draw(last, current);
last = current
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 13
    Maybe it's a variable of a dependancy, and acording to the version/platform it may or may not exist, and there's no other way to know what version it is. – WhyNotHugo Feb 14 '12 at 07:51
  • 47
    State variables don't exist before they are assigned - if you draw a line from the previous position to the current position, then set previous = current, it doesn't mean you "don't know your variables" on the first call. And writing an extra line of code to initialize previous=null outside the draw routine doesn't mean you "know your variables" any better. – Dave Aug 25 '12 at 23:57
  • 1
    Not sure what your point is, Dave. You're correct that they don't exist but, in that case, you shouldn't be trying to use them. Make sure they _do_ exist, that's what I'm suggesting. – paxdiablo Aug 26 '12 at 02:32
  • 6
    My point is that a block "if last: draw(last, current); last=current" is easy to understand and not poor programming. Adding a "try/except" to check for the existence of "last" before being able to test it detracts from readability of that code. – Dave Aug 26 '12 at 17:58
  • 1
    @Dave: doesn't "if last: draw(last, current); last=current" cause an exception if last doesn't exist? – jnhghy - Alexandru Jantea Jul 21 '14 at 12:02
  • 35
    "The use of variables that haven't been defined is actually a bad thing in any language" Spare me the condescending speech. Some of us use Python for simple mathematics or statistics scripts using IDEs such as Spyder which work like Matlab. It makes sense sometimes in those environments to allow the user to define variables in the global console and check otherwise if they are undeclared in the script like when doing mathematics in Matlab. – Ricardo Magalhães Cruz Dec 27 '15 at 23:07
  • 20
    @Ricardo, perhaps, rather than assuming it's condescension, you may want to at least *consider* the possibility that it's just good advice from someone who *may* be more knowledgeable :-) Or would you consider it equally patronising if I advised against unconstrained use of global variables, spaghetti code, god objects, releasing untested code, or writing operating systems in COBOL? My answer stated why I thought it was a bad idea (and there was nothing in the question indicating why OP thought it was necessary) but still provided a way on the off chance they really wanted to do it. – paxdiablo Dec 28 '15 at 04:30
  • 6
    Python is used in a lot of settings. I am working in a math PhD. Within the context of Spyder, it makes sense. It's like using matlab. – Ricardo Magalhães Cruz Dec 29 '15 at 09:26
  • 2
    @paxdiablo In this case, it's too bad the creators of Python didn't take a page from VB and provide some sort of `Option Explicit` for those of us who prefer compile-time warnings to run-time exceptions or crashes (or, arguably worse, hours of needless debugging). – Bond Dec 29 '15 at 15:06
  • 1
    In support of @RicardoCruz commentary: it also makes sense when a script may be run either within `pyspark-shell` or from `spark-submit`: the code `if not sc:` would handle the latter case .. except that python complains `NameError: sc is not defined` – WestCoastProjects Jun 04 '17 at 18:45
  • @paxdiablo how strict are you about the future usage of your code? Being alone home and running it always in the same way is not the same as letting a community include your module, or execute it directly from the shell or with runpy.run_path. Moreover event-driven programming might require you do not exactly know what has been done previously. I agree that it "is likely to result in unpredictable behaviour" it's up to us to test conveniently about possible cases – Lorenzo Jan 16 '18 at 10:23
  • 1
    Lorenzo, you're correct, I am more lax about correctness when I write code for my purposes only (since I can easily debug issues on the fly). However, that's *not* the code I post on SO :-) – paxdiablo Jul 31 '18 at 00:38
  • 2
    Although this is "almost always a bad thing" in most programs one exception is Jupyter notebooks where there is overall confusion around the order that code was executed and often you want to remove stuff from memory (using `del ...`) if it still exists. That's what I use this for anyway. Thanks! – Bill Jun 13 '19 at 19:12
  • There may be good reasons to test if a variable exist in python. e.g. : Testing the existence of var after `for var in some_generator():` is a very simple way to test if you entered the loop at least once. – Camion Jan 18 '23 at 22:32
  • @Camion, that won't work unless you guarantee the variable doesn't already exist before the loop starts (so you would have to `del` it, which is a problem if it doesn't exist, needing a `try/except` anyway, defeating the intent of the question). A better way would be set a *flag* to false before the loop and set it to true within the loop, then use the flag which you *know* exists. Then you're not relying on the existence of variables that may or may not have been bound beforehand. – paxdiablo Jan 19 '23 at 03:11
  • Of course, @paxdiablo, I didn't enter in a detailed explanation in a simple comment. – Camion Jan 20 '23 at 09:47
91

A simple way is to initialize it at first saying myVar = None

Then later on:

if myVar is not None:
    # Do something
Roger Dahl
  • 15,132
  • 8
  • 62
  • 82
Chinedum Ukejianya
  • 1,196
  • 7
  • 5
  • 3
    There is much that is to be improved in this answer. Rather - A simple way is to declare it first. `myVar = none # do stuff... if not myVar: # give myVar a value myVar = 'something'` – Shawn Mehan Nov 25 '15 at 17:17
  • 1
    i like this one a lot because i set things to None in my `except` statements – Kermit Jul 05 '18 at 16:22
  • 2
    why not something like: `if myVar: # Do something` This avoids the need to read a double negative – jjisnow Jul 09 '18 at 10:46
  • 2
    @jjisnow Because you want this condition to be true even if `myVar` is an empty list, zero, empty string etc. – Gabriel Jul 27 '18 at 18:09
  • 12
    @jjisnow `if myVar: # Do something` throws `NameError` in python3 if myVar is not declared – Agile Bean Jul 31 '18 at 14:42
  • 1
    ...but what if you _don't know_ if a variable has been defined or not? What if you don't control it? – TheTechRobo the Nerd May 31 '20 at 18:27
  • This answer is useful for developing an approach to clean sql client connection code that may need to always check if a connection has been closed to avoid memory leaks -- there is a lot of possibilities once you involve the network and an application that depends on it on top. – Jon Oct 07 '20 at 22:36
  • Shawn, I'm not a big fan of the `if not myVar` for checking against `None`. Specifically, it will *also* identify, zero, empty strings, and empty collections (which you may wish to use as the "real" data). Explicit checks using `is [not] None` are usually better. – paxdiablo Feb 19 '22 at 00:14
27

Using try/except is the best way to test for a variable's existence. But there's almost certainly a better way of doing whatever it is you're doing than setting/testing global variables.

For example, if you want to initialize a module-level variable the first time you call some function, you're better off with code something like this:

my_variable = None

def InitMyVariable():
  global my_variable
  if my_variable is None:
    my_variable = ...
  • 2
    I try not to use this, because it pollutes the global namespace. One way to avoid this is to make the function a class, with my_variable as a class variable, and defining __call__ as the body of the existing function, but that's a pain to code and opens up a bunch of other questions. I prefer to use function attributes, see below. – samwyse Mar 25 '14 at 14:52
25

for objects/modules, you can also

'var' in dir(obj)

For example,

>>> class Something(object):
...     pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
Wyrmwood
  • 3,340
  • 29
  • 33
12

I will assume that the test is going to be used in a function, similar to user97370's answer. I don't like that answer because it pollutes the global namespace. One way to fix it is to use a class instead:

class InitMyVariable(object):
  my_variable = None

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

I don't like this, because it complicates the code and opens up questions such as, should this confirm to the Singleton programming pattern? Fortunately, Python has allowed functions to have attributes for a while, which gives us this simple solution:

def InitMyVariable():
  if InitMyVariable.my_variable is None:
    InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
Community
  • 1
  • 1
samwyse
  • 2,760
  • 1
  • 27
  • 38
9

catch is called except in Python. other than that it's fine for such simple cases. There's the AttributeError that can be used to check if an object has an attribute.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
6

A way that often works well for handling this kind of situation is to not explicitly check if the variable exists but just go ahead and wrap the first usage of the possibly non-existing variable in a 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
  • 15,132
  • 8
  • 62
  • 82
6

I created a custom function.

def exists(var):
     return var in globals()

Then the call the function like follows replacing variable_name with the variable you want to check:

exists("variable_name")

Will return True or False

Psychzander
  • 107
  • 14
Abhishek R
  • 4,087
  • 1
  • 17
  • 21
3

Like so:

def no(var):
    "give var as a string (quote it like 'var')"
    assert(var not in vars())
    assert(var not in globals())
    assert(var not in vars(__builtins__))
    import keyword
    assert(var not in keyword.kwlist)

Then later:

no('foo')
foo = ....

If your new variable foo is not safe to use, you'll get an AssertionError exception which will point to the line that failed, and then you will know better. Here is the obvious contrived self-reference:

no('no')

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-88-d14ecc6b025a> in <module>
----> 1 no('no')

<ipython-input-86-888a9df72be0> in no(var)
      2     "give var as a string (quote it)"
      3     assert( var not in vars())
----> 4     assert( var not in globals())
      5     assert( var not in vars(__builtins__))
      6     import keyword

AssertionError: 
RGD2
  • 443
  • 3
  • 8
  • in python3, the line with `__builtins__` should be replaced with: import builtins assert( var not in vars(builtins)) And it's probably not a bad practise to finish out the definition with a `return True` line, so you can write stuff like `assert no('foo')` which is clearer. – RGD2 Apr 01 '21 at 02:00
2

It may not be performant, but you generalise the solution to a function that checks both local variables and global variables.

import inspect
def exists_var(var_name):
    frame = inspect.currentframe()
    try:
        return var_name in frame.f_back.f_locals or var_name in globals()
    finally:
        del frame

Then you can use it like this:

exists_var('myVar')
James
  • 2,756
  • 17
  • 19
1

Short variant:

my_var = some_value if 'my_var' not in globals() else my_var:
Давид Шико
  • 362
  • 1
  • 4
  • 13
  • This is good for a use case we encounter in Databricks. It is not a very good system for detailed programs because running one notebook from another will clobber any same named variables. To reduce clobbered, use preexisting value if it exists – pauljohn32 Nov 22 '21 at 04:14
0

This was my scenario:

for i in generate_numbers():
    do_something(i)
# Use the last i.

I can’t easily determine the length of the iterable, and that means that i may or may not exist depending on whether the iterable produces an empty sequence.

If I want to use the last i of the iterable (an i that doesn’t exist for an empty sequence) I can do one of two things:

i = None  # Declare the variable.
for i in generate_numbers():
    do_something(i)
use_last(i)

or

for i in generate_numbers():
    do_something(i)
try:
    use_last(i)
except UnboundLocalError:
    pass  # i didn’t exist because sequence was empty.

The first solution may be problematic because I can’t tell (depending on the sequence values) whether i was the last element. The second solution is more accurate in that respect.

Jens
  • 8,423
  • 9
  • 58
  • 78
  • OP asked "Are there other ways without exceptions?" - Exceptions are slow and propagate, so if `use_last(i)` raises `UnboundLocalError` you'll get the wrong answer and no error message. That said, `hasattr` has the same issue so I guess this is the most "pythonic" answer. – c z Dec 09 '20 at 09:20
0

Also a possibility for objects, use __dict__.

class A(object):
    def __init__(self):
        self.m = 1

a = A()
assert "m" in a.__dict__
assert "k" not in a.__dict__
Gulzar
  • 23,452
  • 27
  • 113
  • 201
0

Simple one line:

a=1
exec("try: a \nexcept NameError: print('Does not exist.')\nelse:print(a)")

and do something:

exec("def my_try(): \n\ttry: a \n\texcept NameError: print('Does not exist.Creating a=');a=1;print(a);\n\telse:print(a)\n\n\nmy_try()")
Mihai.Mehe
  • 448
  • 8
  • 13