539

How do you know whether a variable has been set at a particular place in the code at runtime? This is not always obvious because (1) the variable could be conditionally set, and (2) the variable could be conditionally deleted. I'm looking for something like defined() in Perl or isset() in PHP or defined? in Ruby.

if condition:
    a = 42

# is "a" defined here?

if other_condition:
    del a

# is "a" defined here?
Community
  • 1
  • 1
user102008
  • 30,736
  • 10
  • 83
  • 104
  • 12
    Duplicates: http://stackoverflow.com/questions/843277/python-checking-variable-existing, http://stackoverflow.com/questions/750298/easy-way-to-check-that-variable-is-defined-in-python, – carl Oct 20 '09 at 06:50
  • 90
    Please, please, please, do not "conditionally" set a variable. That's just dreadful, horrible design. Always, always, always provide for all logic paths. Please do not continue doing this. – S.Lott Oct 20 '09 at 10:35
  • 2
    +1 to S.Lott anwser. The fact that there is a way to do it doesn't mean you should use it in a fresh project. – Bite code Mar 31 '10 at 13:48
  • 10
    @S.Lott: I have to disagree. When I use `import` to "source" a "config file" (i.e. a file that only has assignments in it), it may very well be that some variable has not been defined there. And `import` is sure cheaper/simpler than `ConfigParser`, so for me pragmatism wins over beauty here. – 0xC0000022L Mar 21 '12 at 00:51
  • 17
    @STATUS_ACCESS_DENIED: That's what defaults are appropriate. First set the defaults. Then import your configuration. Now all variables are defined, either as defaults or overrides in the configuration file. You can easily avoid conditionally setting a variable. – S.Lott Mar 22 '12 at 11:29
  • @S.Lott: What about in a memoizing method? You can return or set conditionally. It's a std in ruby, that way of thinking is why I am here. – MarkJL Jul 20 '16 at 09:49
  • 1
    dumb question here, I know I'm overthinking this... By "conditionally setting a variable", are you saying the **existence** of a variable shouldn't be based on a condition? – dangel Dec 10 '17 at 03:07
  • 1
    @dangel, yes. You may think *"that variable will **never** be referenced if `not condition`"*, however it has been shown time and again (personal experience, at least) that programmers are imperfect and logic flows can in fact be different than expectations. **This is especially true in spiral-development**, where assumptions change and not all code is audited/refactored. It costs "almost nothing" to set the variable regardless of `condition`, even if only used when `condition` is met. – r2evans Jan 22 '18 at 16:34
  • 1
    @0xC0000022L The import machinery is heavy. And it is not intended to be used for "configuration files". If thats the only thing you want, you'd be better of using `exec` or `eval`. However, that would be very insecure in many ways, so I think its worth a simple parser. Anyway, the nearest equivalent to an `isset()` would be `hasattr()`. One could also use `globals().get()` which is capable of returning a default. – Bachsau Apr 15 '18 at 17:08

6 Answers6

773
try:
    thevariable
except NameError:
    print("well, it WASN'T defined after all!")
else:
    print("sure, it was defined.")
phoenix
  • 7,988
  • 6
  • 39
  • 45
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 79
    @Aaron: There are many cases when you don't know whether variable is defined. You can refactor code to avoid this in many, but not all cases. Alex's solution is correct and it the best when refactoing is not possible for some reasons. There is not much information in the question, so I believe only person asked it can select the best way to handle his case. – Denis Otkidach Oct 20 '09 at 07:58
  • 148
    @Aaron, "should" is a 4-letter word -- e.g. no driver "should" ever exceed the speed limit, but that doesn't mean you don't take all proper and needed precautions against those who nevertheless do. Maintaining fragile, undertested legacy code with somewhat-broken design that you inherited from somebody else is a fact of life, and those who can only think of big-bang rewriting from scratch rather than cautiously and incrementally need to re-read Joel's 9-years-old essay http://www.joelonsoftware.com/articles/fog0000000069.html . – Alex Martelli Oct 20 '09 at 14:51
  • 10
    @S.Lott People use it to maintain backwards compatibility. Search for NameError in Python 3.1 source code. There are many instances where "try: var_name except NameError: something_else" is used. Here are a couple of place where it is used: CSV (http://svn.python.org/projects/python/trunk/Lib/csv.py) library and in the ElementTree library (http://svn.python.org/projects/python/trunk/Lib/xml/etree/ElementTree.py). – sc45 Oct 20 '09 at 14:54
  • 24
    This debate is much more interesting that the answer itself, which by the way is 100% correct and let you handle poor legacy code elegantly. – Bite code Mar 31 '10 at 13:46
  • 3
    it depends on the context, in a scripting environment, for example, it's perfectly fine to check if a variable is defined or not, and ad. es. give it a default value. my 2c. – andreabedini Feb 17 '11 at 08:53
  • 2
    @S.Lott - What about a variable in a view template, where it's up to the including code to set the variable? How would you ensure a defined variable in those situations? – Yarin Apr 19 '12 at 03:02
  • 2
    Variables can also be dynamically defined and I don't want my script to stop working just because the variable gets correctly defined only if "x" happens. Upvote! – Pitto Mar 08 '13 at 15:16
  • 1
    Note: If it's a class attribute, you need to use try: self.MyMissingVar except AttributeError: print 'It's not there!' – SilentSteel May 08 '13 at 21:03
  • 2
    Much of the discussion in the other answers assumes that the problem is how to tell whether a symbol has an initial value, whereas the OP made it clear that the question is really whether the symbol has any value at all. None is a value, so a symbol whose value is None DOES have a value "at all". – Mitchell Model Jun 16 '13 at 18:23
  • 1
    [continuing] That is why using a try or checking globals() is necessary. Example: You have a file that performs significant initialization computation whose results you want to assign to global symbols. You want to be able to execfile/exec (Python 2/3) the file from any of a number of modules, some perhaps used in more than one program. However, you only want the initialization performed once during a program's execution. Solution: put the execfile/exec in as many places as you want and wrap the file's contents in a conditional that tests whether one of the symbols it defines has a value. – Mitchell Model Jun 16 '13 at 18:46
  • 16
    Exceptions should be reserved for exceptional cases, not for use as the bastard brother of 'if' :-( – einpoklum Apr 10 '15 at 19:54
  • 3
    See also a general discussion on [when to use exceptions](http://stackoverflow.com/q/77127/1593077) here on SO. – einpoklum Apr 10 '15 at 22:16
  • 2
    Meta discussion linking to this answer http://meta.stackoverflow.com/q/289938/73226 – Martin Smith Apr 10 '15 at 23:15
  • 22
    @einpoklum, **Python** uses exception `StopIteration` within just about **every** `for` statement -- that's how an iterator lets it known that it's all done. And of course, it is *far* from "an exceptional case" for iteration to be done -- indeed, one expects *most* iterations to terminate. Thus, obviously, your opinions on how exceptions "should" be used are **not** correctly applicable to **Python** (other languages have different pragmatics and the question **cannot** be properly treated as "language agnostic" as in the Q you point to). – Alex Martelli Apr 17 '15 at 10:10
  • 3
    I agree with @AlexMartelli: The ability to have undefined variables is a *feature* in Python. As any features, it has some use cases where it is more or less appropriate. But it it certainly *not never* appropriate. Testing for it being defined or not is not less strange than testing for the existence of a file. And Python being a lot about duck typing, using an exception makes perfect sense. And by the way, exceptions *are* the bastard brothers of if:s. – Nicklas Börjesson Jun 10 '15 at 09:32
  • 1
    @habnabit Easy refutal: I'm using `iniparse` to load a config file but want to make sure certain variables were set, or the program can't continue. – Shadur Jun 21 '16 at 08:59
  • stumbled across this problem while using pyspark with Jupiter (which DOES define SparkContext as sc for you) and Mesos, which does not. This is why we need this sometimes. – fisk Jul 07 '16 at 07:08
  • 1
    python is used for interactive data analysis in say Jupyter notebooks. In this case, it's great to be able to add a check for whether a variable is defined or not before potentially reloading or recomputing a costly variable simply because you changed another portion of code in the cell and reevaluated it. – AatG Sep 22 '16 at 19:45
  • @Shadur irrelevant; `iniparse` doesn't set variables. – habnabit Dec 22 '16 at 00:31
  • 1
    @einpoklum in python `try/except` is not exceptional it is as friendly a part of program control as `if` or `for`. – eric Jan 12 '21 at 00:37
454

'a' in vars() or 'a' in globals()

if you want to be pedantic, you can check the builtins too
'a' in vars(__builtins__)

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 35
    This should be the answer I believe. see http://stackoverflow.com/questions/843277/python-checking-variable-existing – 0atman Nov 04 '10 at 13:41
  • 3
    This is a very idiomatic answer. There is a strong use case here for maps; for example, `if "prop2" in {"prop0": None, "prop1": None}:` – robert Feb 19 '16 at 18:46
  • This answer also works for detecting members other than variables, such as functions, classes, and modules. – aaaantoine Sep 15 '17 at 15:22
  • 3
    **As of** today — **June 2018**: I don't think `vars(__builtin__)` still works (either for Python 2 or 3). I believe `vars(__builtins__)` _(mind the plural ;-))_ should be used for both versions now (tested on: Python 2.7.10 and Python 3.6.1). –  Jun 12 '18 at 05:35
  • 2
    Why not locals() too, why not dir()? – AndresVia Oct 30 '18 at 13:45
  • 2
    @AndresVia `globals()` is a superset of `locals()`. – KeyC0de Feb 29 '20 at 11:16
  • 1
    This should be the accepted answer. It looks much better when embedded into an if structure that checks for other conditions. – Francesco Jul 03 '20 at 19:27
  • 1
    I like this one better: `a = globals().get('a','@')` Thanks @Bachsau – Quin May 10 '22 at 01:55
165

I think it's better to avoid the situation. It's cleaner and clearer to write:

a = None
if condition:
    a = 42
divegeek
  • 4,795
  • 2
  • 23
  • 28
  • 9
    If you like to do it that way you should make the initial value unique so you can distinguish from something setting `a` to `None` ie. `UNDEFINED=object();a=UNDEFINED` then you can test with `a is not UNDEFINED` – John La Rooy Oct 20 '09 at 07:03
  • 19
    This is a common use of None. It's literally the semantic meaning of None-- it's nothing, nada, zip. It exists, but has "no value". Using a non-None value is useful if None can come up in an assignment and so on, but this is not so common that avoiding None should be standard practice. For example, in the question, a would only ever be 42 or undefined. Changing undefined to having a value of None results in no loss of information. – Devin Jeanpierre Feb 03 '10 at 05:27
  • 6
    This is THE way, not sure why people think using a LONG and DIRTY try/except construct to get this done. ALSO this is very useful when using keyword args in class member functions where you don't want to hard-code the default values into the parameter list (you just define the default value as a class member). – FizxMike Feb 14 '14 at 17:13
  • 1
    @DevinJeanpierre That's not necessarily true. If you want to create some client library for a JSON API that treats a `null` value as different from an unspecified value (eg. `None` sets the actual JSON value to `null`, whereas an unspecified leaves it out of the JSON message entirely, which makes the API use a default or calculate from other attributes), you need to either differentiate `None` from `Undefined`, or `None` from JSON `null`. It's incredibly short-sighted to think that `None` can't or shouldn't ever be used as distinct from a value that is explicitly unspecified or undefined. – Taywee Jun 24 '16 at 05:36
  • @Taywee sure. "Using a non-None value is useful if None can come up in an assignment and so on, but this is not so common that avoiding None should be standard practice." If a non-None value can come up, then None is not acceptable, and this whole pattern is error-prone. – Devin Jeanpierre Jun 28 '16 at 17:38
  • 9
    Providing a default value (which is what this answer is doing) is far different than testing the existence of a variable. There may be much overlap in the use cases, but if you want to see if something has been defined, you'll never know with this method. – Tim S. May 22 '17 at 17:26
  • An even better solution is: `if condition: TeXx = Object(); else: TeXx = None; something.setEnabled(isinstance(TeXx, xmlDOM));`; because let's say I redefine the object as a str or file, not only do I check for None, but it's the right `is not None` – Danny Holstein Mar 24 '23 at 16:47
25
try:
    a # does a exist in the current namespace
except NameError:
    a = 10 # nope
Jerub
  • 41,746
  • 15
  • 73
  • 90
sc45
  • 1,916
  • 2
  • 16
  • 25
  • 11
    Exceptions should only be used in exceptional cases. See [this discussion](http://stackoverflow.com/q/77127/1593077) – einpoklum Apr 10 '15 at 22:17
  • 22
    @einpoklum This is true for most languages, but in Python exceptions are used more often, see e.g. http://stackoverflow.com/questions/3086806 – sdcvvc Apr 27 '15 at 20:32
  • 4
    Hmm, strange but true, apparently. I still think that's not a Good Idea (TM) but, well, can't argue with community customs. – einpoklum Apr 28 '15 at 19:43
  • 3
    Better use the `if 'a' in vars() or 'a' in globals()` solution mentioned above, which does not require an exception – Ron Kalian Oct 30 '17 at 11:07
  • 1
    try/except is what you do in python. what is a code smell in one language is a feature in another. – eric Jan 09 '18 at 03:20
  • Python definitely encourages you to use exceptions more frequently. In many situations instead of specifically checking if an action is possible you instead should just catch the exception. Do this cleanly by making sure you're only catching exactly the exception type you'd expect. The above answer is a great pythonic solution. (Also exceptions in Python are cheap with little overhead) – Chris Aug 13 '22 at 23:13
6

For this particular case it's better to do a = None instead of del a. This will decrement reference count to object a was (if any) assigned to and won't fail when a is not defined. Note, that del statement doesn't call destructor of an object directly, but unbind it from variable. Destructor of object is called when reference count became zero.

Denis Otkidach
  • 32,032
  • 8
  • 79
  • 100
5

One possible situation where this might be needed:

If you are using finally block to close connections but in the try block, the program exits with sys.exit() before the connection is defined. In this case, the finally block will be called and the connection closing statement will fail since no connection was created.

xsreality
  • 344
  • 4
  • 12