0
a = None

b = 'Test'

if a is None or b is None:
    print('Test')

this version is obviously working but:

if (a or b) is None:
   print('Test')

Expected would be the same result but it evaluates to False, why?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Sentinan
  • 89
  • 2
  • 7
  • 5
    Because `(a or b) is b`. `(a and b) is None`. It's not clear why you thought the two different things would have the same result. – jonrsharpe Dec 13 '18 at 14:21
  • why `is b` , what is the full syntax here? i simply want to shorten the `if a is X or b is X or....` – Sentinan Dec 13 '18 at 14:29
  • @Sentinan that's the point! you cannot "shorten" it like that, what you wrote in the second version is an entirely different thing. A shorter, but truly equivalent expression would be: `if not a or not b:` – Óscar López Dec 13 '18 at 14:33
  • Possible duplicate of [Compare multiple variables to the same value in "if" in Python?](https://stackoverflow.com/questions/8641008/compare-multiple-variables-to-the-same-value-in-if-in-python) – jonrsharpe Dec 13 '18 at 14:44

3 Answers3

6

In Python, an or statement does not just return True or False, it returns the first of it's arguments that is "truthy".

In your code, the following happens when evaluating (a or b) is None:

  1. None is falsy, and a is None, so a or b returns b.
  2. b is not None.
  3. (a or b) is None resolves to False.
Zags
  • 37,389
  • 14
  • 105
  • 140
4

Operator precedence and evaluation rules of boolean expressions work a bit different in Python. This is not doing what you imagine:

(a or b) is None

The above condition is asking whether the result of evaluating (a or b) is None, and it will never be None with the current values of a and b; a or b will return 'Test' (the value of b), because a is None. If you want to test if either one of two values is None, only the first syntax is valid:

a is None or b is None

Just to be clear, in Python x or y will return the value of the first non-false expression, and None, [], {}, '', 0 and False are considered false. If what you want is to shorten the expression a bit, this is equivalent to the first version of your code:

if not a or not b:
Óscar López
  • 232,561
  • 37
  • 312
  • 386
0

If you want to be super brief, you can used the following construction:

if None in (a, b):
    print('Test')

Please note that while this will work in the majority of cases, the expression is not exactly equivalent to a is None or b is None but rather a == None or b == None. See explanation of why this is not the same thing.

Martin Frodl
  • 667
  • 4
  • 11