1

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.

Adirio
  • 5,040
  • 1
  • 14
  • 26
  • 1
    Does this answer your question? [How do "and" and "or" act with non-boolean values?](https://stackoverflow.com/questions/47007680/how-do-and-and-or-act-with-non-boolean-values). TL;DR: `and` returns the first **Falsy** value if there are any, else return the last value in the expression. `or` returns the first **Truthy** value if there are any, else return the last value in the expression. – Tomerikoo Sep 07 '20 at 06:52
  • @Tomerikoo actually it does. I thought it returned `False` if there was a falsy value instead of returning the falsy value itself. – Adirio Sep 07 '20 at 06:58

1 Answers1

1

why is it not consistent with the behavior shown for and? I was expecting both first and cases to return False.

It's entirely consistent.

and returns the first operand if it's "falsy", otherwise the second; or returns the first operand if it's "truthy", otherwise the second. Neither converts its operands to booleans.

None is "falsy", since and returns the first operand if falsy None and x returns None, regardless of x.

Also your table is pretty confusing as | and & are actual Python operators (but not boolean operators, or short-circuiting).

Masklinn
  • 34,759
  • 3
  • 38
  • 57