Is it set?

You don’t always know if your variables and list elements exist. That might seem like a careless position to find yourself in but there are all sorts of reasons why this doubt might be reasonable. This is especially true of associative arrays (PHP) and dictionaries (Python) which may have been passed in to a function from who knows where. It’s not the business of a function to worry too much about the calling context – but it does need to concern itself with the validity of the data it has been given. If you think that it’s possible that a variable or element does not exist you can save yourself from unintended consequences by testing before use.

PHP Code Example

In PHP, isset() is the Swiss Army knife of existence checks. It allows us to check for existence or null and, unlike other most other functions, won’t complain if it’s given an unintialised variable or element to work with.

Here we check a variable and an element with isset() before using the null coalescing operator to assign a value to an associative array element if it is not yet declared.

if (! isset($nonexistent)) {
    print "nothing to see here\n";
}

$hats = ['homburg' => 4.00];
if (! isset($hats['trilby'])) {
   print "what about the trilby?\n"; 
}

$mytrilby = $hats['trilby'] ?? 6.0;
print "{$mytrilby}\n";

Output:

nothing to see here
what about the trilby?
6

Python Code Example

For the Python version, we use the Python membership operator not in in conjunction with the built-in locals() and globals() functions. We then demonstrate another approach – essentially asking for forgiveness rather than permission by accessing a variable in a try clause. not in works well with user-defined dictionaries too.

Python does not support a null coalescing operator, but the dictionary get() method allows for default value substitution.

if 'nonexistent' not in locals() and 'nonexistent' not in globals():
    print("nothing to see here")

try: nonexistent
except NameError: print("nothing to see here 2")

hats = {'homburg': 4.00}
if "trilby" not in hats:
   print("what about the trilby?")

mytrilby = hats.get('trilby', 6.0)
print(f"{mytrilby}")

Output:

nothing to see here
nothing to see here 2
what about the trilby?
6.0

Discussion

There’s quite a lot going on here, so let’s break it down a little. In PHP-land the isset() function is a flexible tool for testing variable and element existence. Since the variable $nonexistent has not been declared this conditional will fire:

if (! isset($nonexistent)) {
    print "nothing to see here\n";
}

Python does not have a direct equivalent to isset() but there are good alternatives. First of all, the locals() and globals() functions both return dictionaries representing all variables in local and global scope respectively. That allows us to check whether the relevant key is present in each of the dictionaries. If not, then we can be sure that that the nonexistent variable lives up to its name (or it would do if it, er, existed).

if 'nonexistent' not in locals() and 'nonexistent' not in globals():
    print("nothing to see here")

This fragment assumes some wider knowledge. First of all, a dictionary is the Python equivalent of an associative array. The in operator can be used with sequences (lists, tuples, strings) and dictionaries. It will resolve to True if the value of the left hand operand can be found within the data referenced by the right hand operand. So, in this example, we look inside the dictionaries returned by locals() (symbols within local scope) and globals() (symbols within global scope) for the key ‘nonexistent’. We don’t find it, of course, so, because in each case we negate in with not the conditional clause is fired. There is no nonexistent.

If we attempt to access a non-existent variable in PHP we trigger a warning:

PHP Warning:  Undefined variable $nonexistent in ...

The sort warning that legacy PHP systems tend to generate by the thousand. Python is stricter than this – it generates a NameError exception:

NameError: name 'nonexistent' is not defined

This strictness provides us with another opportunity to check for a variable’s existence before working with it:

try: nonexistent
except NameError: print("nothing to see here 2")

We attempt to access nonexistent in a try clause. If nonexistent does not, in fact, exist then a NameError is raised, and the except clause is invoked. Because we are handling the exception, we are trusted to manage the error.

Note See the Python documentation for more on exceptions in Python.

In PHP isset() will check an associative array for an element.

$hats = ['homburg' => 4.00];
if (! isset($hats['trilby'])) {
   print "what about the trilby?\n"; 
}

As we have seen, in Python we can use not in to check a dictionary.

hats = {'homburg': 4.00}
if "trilby" not in hats:
   print("what about the trilby?")

Incidentally, we could also use the try/except approach

hats = {'homburg': 4.00}
try: hats['trilby']
except KeyError: print("what about the trilby?")

Note that, this time, we need to catch a KeyError rather than a NameError.

Of course, where a variable or element does not exist, we often need to set a default value. Luckily PHP’s null coalescing operator (??) will implicitly apply an isset() check to its left-hand operand. In other words, we can do this without triggering an error:

$hats = ['homburg' => 4.00];
$mytrilby = $hats['trilby'] ?? 6.0;
print "{$mytrilby}\n";

Python is not so forgiving. However, the dictionary get() method allows an optional second argument (the first is the name of the key whose value the method will return on success). This is a default value which will be returned if the given key does not exist in the dictionary

mytrilby = hats.get('trilby', 6.0)
print(f"{mytrilby}")

See also

Further Reading:


Stay up to date with the Python for PHP Programmers project


Yes! Please sign me up to this newsletter


Photo by Sigmund on Unsplash