if (foo or bar or baz) is None:
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Cool Puzzler LoFi
--
Chapters
00:00 If (Foo Or Bar Or Baz) Is None:
01:02 Answer 1 Score 4
01:26 Accepted Answer Score 5
02:33 Answer 3 Score 0
02:56 Answer 4 Score 0
03:23 Thank you
--
Full question
https://stackoverflow.com/questions/1582...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #styles #correctness
#avk47
ACCEPTED ANSWER
Score 5
The short-circuiting behavior causes foo or bar or baz to return the first of the three values that is boolean-true, or the last value if all are boolean-false.  So it basically means "if all are false and the last one is None".
Your changed version is slightly different.  if None in (opts.foo, opts.bar, opts.baz) will, for instance, enter the if block if opts.foo is None and the other two are 1, whereas the original version will not (because None or 1 or 1 will evaluate to 1, which is not None).  Your version will enter the if when any of the three is None, regardless of what the other two are, whereas the original version will enter the if only if the last is None and the other two are any boolean-false values.
Which of the two versions you want depends on how the rest of the code is structured and what values the options might take (in particular, whether they might have boolean-false values other than None, such as False or 0 or an empty string).  Intuitively your version does seem more reasonable, but if the code has peculiar tricks like this in it, you never know what corner cases might emerge.
ANSWER 2
Score 4
It's behaving that way because or is an short-circuit operator, details are in docs. Thus your first if statement is equal to:
if opts.baz is None
We could guess what author of that code expected. I think that, as you mentioned, he thought of using not all([opts.foo, opts.bar, opts.baz]).
ANSWER 3
Score 0
I would prefer
 if any(i is None for i in (opts.foo, opts.bar, opts.baz))
as it exactly expresses the intended goal.
OTOH,
not all([opts.foo, opts.bar, opts.baz])
does check for falseness, not for None.
The original code doesn't seem to make sense; it seems to have been written by someone unaware what they are doing.
ANSWER 4
Score 0
let's try both two of your code:
In [20]: foo = True
In [22]: bar = None
In [23]: baz = None
In [24]: foo or bar or baz
Out[24]: True
In [25]: (foo or bar or baz) is None
Out[25]: False
In [28]: ((foo or bar or baz) is None) == (None in (foo, bar, baz))
Out[28]: False
You can see your rewrite is not same as the original code.
Your first condition only return True when all of your variables is None
In [19]: (None or None or None) is None
Out[19]: True
so you can rewrite your first condition to:
if foo == bar == bar == None: