Sebastian Raschka, 03/2014
Code was executed in Python 3.4.0

True and False in the datetime module

Pointed out in a nice article "A false midnight" at http://lwn.net/SubscriberLink/590299/bf73fe823974acea/:

"it often comes as a big surprise for programmers to find (sometimes by way of a hard-to-reproduce bug) that,
unlike any other time value, midnight (i.e. datetime.time(0,0,0)) is False.
A long discussion on the python-ideas mailing list shows that, while surprising,
that behavior is desirable—at least in some quarters."

In [17]:
import datetime

print('"datetime.time(0,0,0)" (Midnight) evaluates to', bool(datetime.time(0,0,0)))

print('"datetime.time(1,0,0)" (1 am) evaluates to', bool(datetime.time(1,0,0)))
"datetime.time(0,0,0)" (Midnight) evaluates to False
"datetime.time(1,0,0)" (1 am) evaluates to True

Boolean True

In [83]:
my_true_val = True


print('my_true_val == True:', my_true_val == True)
print('my_true_val is True:', my_true_val is True)

print('my_true_val == None:', my_true_val == None)
print('my_true_val is None:', my_true_val is None)

print('my_true_val == False:', my_true_val == False)
print('my_true_val is False:', my_true_val is False)

print(my_true_val
if my_true_val:
    print('"if my_true_val:" is True')
else:
    print('"if my_true_val:" is False')
    
if not my_true_val:
    print('"if not my_true_val:" is True')
else:
    print('"if not my_true_val:" is False')
my_true_val == True: True
my_true_val is True: True
my_true_val == None: False
my_true_val is None: False
my_true_val == False: False
my_true_val is False: False
"if my_true_val:" is True
"if not my_true_val:" is False

Boolean False

In [76]:
my_false_val = False


print('my_false_val == True:', my_false_val == True)
print('my_false_val is True:', my_false_val is True)

print('my_false_val == None:', my_false_val == None)
print('my_false_val is None:', my_false_val is None)

print('my_false_val == False:', my_false_val == False)
print('my_false_val is False:', my_false_val is False)


if my_false_val:
    print('"if my_false_val:" is True')
else:
    print('"if my_false_val:" is False')
    
if not my_false_val:
    print('"if not my_false_val:" is True')
else:
    print('"if not my_false_val:" is False')
my_false_val == True: False
my_false_val is True: False
my_false_val == None: False
my_false_val is None: False
my_false_val == False: True
my_false_val is False: True
"if my_false_val:" is False
"if not my_false_val:" is True

None 'value'

In [62]:
my_none_var = None

print('my_none_var == True:', my_none_var == True)
print('my_none_var is True:', my_none_var is True)

print('my_none_var == None:', my_none_var == None)
print('my_none_var is None:', my_none_var is None)

print('my_none_var == False:', my_none_var == False)
print('my_none_var is False:', my_none_var is False)


if my_none_var:
    print('"if my_none_var:" is True')
else:
    print('"if my_none_var:" is False')

if not my_none_var:
    print('"if not my_none_var:" is True')
else:
    print('"if not my_none_var:" is False')
my_none_var == True: False
my_none_var is True: False
my_none_var == None: True
my_none_var is None: True
my_none_var == False: False
my_none_var is False: False
"if my_none_var:" is False
"if not my_none_var:" is True

Empty String

In [61]:
my_empty_string = ""

print('my_empty_string == True:', my_empty_string == True)
print('my_empty_string is True:', my_empty_string is True)

print('my_empty_string == None:', my_empty_string == None)
print('my_empty_string is None:', my_empty_string is None)

print('my_empty_string == False:', my_empty_string == False)
print('my_empty_string is False:', my_empty_string is False)


if my_empty_string:
    print('"if my_empty_string:" is True')
else:
    print('"if my_empty_string:" is False')
    
if not my_empty_string:
    print('"if not my_empty_string:" is True')
else:
    print('"if not my_empty_string:" is False')
my_empty_string == True: False
my_empty_string is True: False
my_empty_string == None: False
my_empty_string is None: False
my_empty_string == False: False
my_empty_string is False: False
"if my_empty_string:" is False
"if my_empty_string:" is True

Empty List

It is generally not a good idea to use the == to check for empty lists...

In [67]:
my_empty_list = []


print('my_empty_list == True:', my_empty_list == True)
print('my_empty_list is True:', my_empty_list is True)

print('my_empty_list == None:', my_empty_list == None)
print('my_empty_list is None:', my_empty_list is None)

print('my_empty_list == False:', my_empty_list == False)
print('my_empty_list is False:', my_empty_list is False)


if my_empty_list:
    print('"if my_empty_list:" is True')
else:
    print('"if my_empty_list:" is False')
    
if not my_empty_list:
    print('"if not my_empty_list:" is True')
else:
    print('"if not my_empty_list:" is False')


    
my_empty_list == True: False
my_empty_list is True: False
my_empty_list == None: False
my_empty_list is None: False
my_empty_list == False: False
my_empty_list is False: False
"if my_empty_list:" is False
"if not my_empty_list:" is True

[0]-List

In [70]:
my_zero_list = [0]


print('my_zero_list == True:', my_zero_list == True)
print('my_zero_list is True:', my_zero_list is True)

print('my_zero_list == None:', my_zero_list == None)
print('my_zero_list is None:', my_zero_list is None)

print('my_zero_list == False:', my_zero_list == False)
print('my_zero_list is False:', my_zero_list is False)


if my_zero_list:
    print('"if my_zero_list:" is True')
else:
    print('"if my_zero_list:" is False')
    
if not my_zero_list:
    print('"if not my_zero_list:" is True')
else:
    print('"if not my_zero_list:" is False')
my_zero_list == True: False
my_zero_list is True: False
my_zero_list == None: False
my_zero_list is None: False
my_zero_list == False: False
my_zero_list is False: False
"if my_zero_list:" is True
"if not my_zero_list:" is False

List comparison

List comparisons are a handy way to show the difference between == and is.
While == is rather evaluating the equality of the value, is is checking if two objects are equal. The examples below show that we can assign a pointer to the same list object by using =, e.g., list1 = list2.
a) If we want to make a shallow copy of the list values, we have to make a little tweak: list1 = list2[:], or
b) a deepcopy via list1 = copy.deepcopy(list2)

Possibly the best explanation of shallow vs. deep copies I've read so far:

*** "Shallow copies duplicate as little as possible. A shallow copy of a collection is a copy of the collection structure, not the elements. With a shallow copy, two collections now share the individual elements. Deep copies duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated."***

(via S.Lott on StackOverflow)

a) Shallow vs. deep copies for simple elements

List modification of the original list doesn't affect
shallow copies or deep copies if the list contains literals.

In [11]:
from copy import deepcopy

my_first_list = [1]
my_second_list = [1]
print('my_first_list == my_second_list:', my_first_list == my_second_list)
print('my_first_list is my_second_list:', my_first_list is my_second_list)

my_third_list = my_first_list
print('my_first_list == my_third_list:', my_first_list == my_third_list)
print('my_first_list is my_third_list:', my_first_list is my_third_list)

my_shallow_copy = my_first_list[:]
print('my_first_list == my_shallow_copy:', my_first_list == my_shallow_copy)
print('my_first_list is my_shallow_copy:', my_first_list is my_shallow_copy)

my_deep_copy = deepcopy(my_first_list)
print('my_first_list == my_deep_copy:', my_first_list == my_deep_copy)
print('my_first_list is my_deep_copy:', my_first_list is my_deep_copy)

print('\nmy_third_list:', my_third_list)
print('my_shallow_copy:', my_shallow_copy)
print('my_deep_copy:', my_deep_copy)

my_first_list[0] = 2
print('after setting "my_first_list[0] = 2"')
print('my_third_list:', my_third_list)
print('my_shallow_copy:', my_shallow_copy)
print('my_deep_copy:', my_deep_copy)
my_first_list == my_second_list: True
my_first_list is my_second_list: False
my_first_list == my_third_list: True
my_first_list is my_third_list: True
my_first_list == my_shallow_copy: True
my_first_list is my_shallow_copy: False
my_first_list == my_deep_copy: True
my_first_list is my_deep_copy: False

my_third_list: [1]
my_shallow_copy: [1]
my_deep_copy: [1]
after setting "my_first_list[0] = 2"
my_third_list: [2]
my_shallow_copy: [1]
my_deep_copy: [1]

b) Shallow vs. deep copies if list contains other structures and objects

List modification of the original list does affect
shallow copies, but not deep copies if the list contains compound objects.

In [13]:
my_first_list = [[1],[2]]
my_second_list = [[1],[2]]
print('my_first_list == my_second_list:', my_first_list == my_second_list)
print('my_first_list is my_second_list:', my_first_list is my_second_list)

my_third_list = my_first_list
print('my_first_list == my_third_list:', my_first_list == my_third_list)
print('my_first_list is my_third_list:', my_first_list is my_third_list)

my_shallow_copy = my_first_list[:]
print('my_first_list == my_shallow_copy:', my_first_list == my_shallow_copy)
print('my_first_list is my_shallow_copy:', my_first_list is my_shallow_copy)

my_deep_copy = deepcopy(my_first_list)
print('my_first_list == my_deep_copy:', my_first_list == my_deep_copy)
print('my_first_list is my_deep_copy:', my_first_list is my_deep_copy)

print('\nmy_third_list:', my_third_list)
print('my_shallow_copy:', my_shallow_copy)
print('my_deep_copy:', my_deep_copy)

my_first_list[0][0] = 2
print('after setting "my_first_list[0][0] = 2"')
print('my_third_list:', my_third_list)
print('my_shallow_copy:', my_shallow_copy)
print('my_deep_copy:', my_deep_copy)
my_first_list == my_second_list: True
my_first_list is my_second_list: False
my_first_list == my_third_list: True
my_first_list is my_third_list: True
my_first_list == my_shallow_copy: True
my_first_list is my_shallow_copy: False
my_first_list == my_deep_copy: True
my_first_list is my_deep_copy: False

my_third_list: [[1], [2]]
my_shallow_copy: [[1], [2]]
my_deep_copy: [[1], [2]]
after setting "my_first_list[0][0] = 2"
my_third_list: [[2], [2]]
my_shallow_copy: [[2], [2]]
my_deep_copy: [[1], [2]]

Some Python oddity:

In [1]:
a = 1
b = 1
print('a is b', bool(a is b))
True

a = 999
b = 999
print('a is b', bool(a is b))
a is b True
a is b False