Boolean and None in Python


In this article, we have explored the two important concepts namely boolean and none in Python.

Let’s say there is a variable, x.

  1. If x, then y.
  2. If x is not None, then y.
    Are these two statements equivalent, or rather will y be executed twice?

Why does this matter?

This test checks whether x has been assigned to or not, which is helpful when debugging and looking through many lines of code.

These two statements would look like this in code, if x is None and y is to print a line.

x = None
if x:
    print ("if x")
if not x:
    print ("if not x")
if x is None:
    print (“if x is None")
if x is not None:
    print ("if x is not None")

This code will yield nothing. Does that mean the two statements are equivalent?

Spoiler alert: no, they are not equivalent - the following examples will show how they differ. Neither are they equivalent vice versa ("if not x" and "if x is None" are also not the same)

Dissecting the code

Let’s examine the statement “If x is not None, then y.” more closely.
This section will define the keywords “is” and “None”.

What is “is”?

It’s an operator that checks whether x and “not None” are pointing to the same object.
E.g.

a = 20.0
b = a
print(a is b)
c = int(a)
print(a is c)
if a == c:
	print ("True")

Python will print True for the condition (a is b), then False for the condition (a is c), then true for (a == c).
That’s because despite a, b and c being equal in value (20.0, 20.0 and 20 respectively), a and b are the same object because b is defined as the value of a, but a and c point to different objects. Hence, a is b and a == c, but a is not c!

What is “None”?

None is a singleton in Python. Its type is NoneType.
It is used to define a null value and only None can be None – it is not equal to 0, False, or an empty string.

What is a singleton?

A singleton is a creational design pattern, which is a mechanism for creating objects and allows for flexibility and the reuse of the code. A singleton creates a specific type of object once, if more types of the object is created, the duplicates are returned. In other words, it ensure that only a single instance of the object is created and that it can be globally accessed throughout the code.

What happens when “if x” is called?

Python expects a Boolean because of the inbuilt Magic Methods and the nonzero method is called.

In other words, with code such as

x = 10
if x == 10:
    print ("x is 10!")

Python evaluates whether the value of x is 10 in the if statement - it is either 10 (so it is True and Python returns the statement "x is 10!"), or it is not 10 (so it is False).

Hence, when if x is called, Python evaluates the statement as Bool(x) to decide whether or not to proceed with the following statement.

Bool(None) happens to be False, so it is not surprising when the code does not return anything. However, x has been assigned the value of None, so the second statement is also False and the code returns nothing.

To check whether the statements are equivalent, we can run a few more statements through python to check.

Examples

First consider the case for testing an empty list.

x = []
if x:
    print ("if x")
if not x:
    print ("if not x")
if x is None:
    print (“if x is None")
if x is not None:
    print ("if x is not None")

This yields if not x if x is not None.
In the first part of the code, Bool([]) returns False, so it is reasonable that there is no output from that part. The reverse is True in the next row so if not x is returned. However in the second part of the code, the value of an empty list is not None, an empty list is a list of zeros so the value should be zero. Hence only the following part, if x is not None is printed.

It is important to note that because [] is not None, one can differentiate between "if x" and "if x is not None" in this case!

Then consider the case for testing a string.

x = "testing"
if x:
    print ("if x")
if not x:
    print ("if not x")
if x is None:
    print (“if x is None")
if x is not None:
    print ("if x is not None")

This yields if x if x is not None.
In the first part of the code, Bool("testing") returns True, so it outputs if x. The reverse is False in the next row so "if not x" is not returned. However in the second part of the code, the value of a string is not None, an empty list is a list of zeros so the value should be zero. Hence only the following part, if x is not None is printed.

Consider the case for an integer value.

x = 42
if x:
    print ("if x")
if not x:
    print ("if not x")
if x is None:
    print (“if x is None")
if x is not None:
    print ("if x is not None")

This yields if x if x is not None.
In the first two conditions of the code, Bool(int) returns True, so if x is printed instead of the other sentence. In the last two conditions, x is an integral value so it is not None and if x is not None is printed.

Conclusion

"if x" and "if x is not None" are not equivalent - the proof can be seen by setting x to different values. Sometimes only the condition from the first statement is executed, sometimes only the second is executed.

Reference links

For more information on booleans, refer to: Boolean