I was trying to fully understand the behavior of None
as a boolean for logical and
and or
operations, so I tried the following code:
for a, b in [(None, False), (None, True), (False, None), (True, None)]:
print(f"{str(a):<5} & {str(b):<5}", a and b)
for a, b in [(None, False), (None, True), (False, None), (True, None)]:
print(f"{str(a):<5} | {str(b):<5}", a or b)
That outputs:
None & False: None
None & True : None
False & None : False
True & None : None
None | False: False
None | True : True
False | None : None
True | None : True
The last two cases of and
are expected due to short-circuiting. If the first statement is False
it returns False
without checking the second one, while if the first one is True
it directly returns the second one. But the first two cases show that None
doesn't have any boolean value.
The last two cases of or
are again expected due to short-circuiting. If the first statment is False
it directly returns the second one, while if the first one is True
it returns True
without checking the second one. But the first two cases show that None
has a negative boolean value.
I understand that the purpose of this negative value is to be able to do things like default values with a = a or 5
, but why is it not consistent with the behavior shown for and
? I was expecting both first and
cases to return False
.