Skip to content

How to Check if a Variable is Defined in Python

Learn Python's best practices for handling undefined variables, including initializing to None and using try...except NameError to avoid NameError exceptions.

Unlike languages such as JavaScript where a variable can be declared without being assigned a value (resulting in undefined), Python requires that a variable be assigned a value before it can be used. Attempting to access a name that hasn't been assigned will immediately raise a NameError. Therefore, "checking if a variable is defined" in Python is primarily about handling potential NameError exceptions or, more ideally, structuring your code to prevent them from occurring.

This guide will explain the Pythonic approach to this problem, which involves initializing variables to None, and will also cover the direct method of using a try...except block to catch a NameError.

Understanding the NameError: Python's "Undefined Variable" Error

In Python, a variable is not "created" until a value is assigned to it. If you try to read from a variable name before its first assignment, the interpreter cannot find that name in the current scope and raises a NameError.

Exmaple of code causing the error:

print(my_string)

Output:

Traceback (most recent call last):
  File "<main.py>", line 1, in <module>
NameError: name 'my_string' is not defined

Method 1: Catching the NameError with try...except

The most direct way to check if a name has been defined is to try using it and catch the NameError if it hasn't. This follows the Python principle of EAFP ("Easier to Ask for Forgiveness than Permission").

Solution:

try:
    print(f"The value of my_string is: {my_string}")
except NameError:
    print("'my_string' was not defined. Initializing it now.")
    my_string = "Hello"

print(f"The final value is: {my_string}")

Output:

'my_string' was not defined. Initializing it now.
The final value is: Hello

Method 2: The Pythonic Approach - Initialize to None

The more common and generally better practice is to ensure a variable is always defined, even if it doesn't have a "real" value yet. The standard way to do this is to initialize it to None. This prevents NameError and turns the check into a simple value comparison.

This approach makes your code's logic and potential states much more explicit and predictable.

Solution:

my_string = None

if my_string is None:
    print("'my_string' is None. Assigning a new value.")
    my_string = "Hello"

print(f"The final value is: {my_string}")

Output:

'my_string' is None. Assigning a new value.
The final value is: Hello

Method 3: Checking locals() or globals() (Advanced)

For introspection or debugging, you can check if a variable name exists as a string key in the dictionaries returned by locals() or globals(). This is generally not recommended for regular application logic.

Solution:

if 'my_string' in locals() or 'my_string' in globals():
    print("my_string is defined.")
else:
    print("my_string is not defined.")

my_string = "I exist now."

if 'my_string' in locals():
    print("Now my_string is defined.")

Output:

my_string is not defined.
Now my_string is defined.

Conclusion

While Python doesn't allow undeclared variables like some other languages, you can effectively manage a variable's state using these methods:

  1. Best Practice (Initialize to None): The most Pythonic and robust approach is to initialize your variables to None at the beginning of their scope. This guarantees they are always defined, and you can then check their state with if my_variable is None:.
  2. Direct Check (try...except): If you absolutely must check for the existence of a name, use a try...except NameError block. This is a valid tool but should be used sparingly for controlling standard program flow.
  3. Advanced (Introspection): For special cases, you can check for the variable's name as a string in the output of locals() or globals(), but this should be avoided in normal application code.

By defaulting to the None initialization pattern, you will write clearer, more predictable, and more maintainable Python code.

Navigation