87
In [20]: print None or False
-------> print(None or False)
False

In [21]: print False or None
-------> print(False or None)
None

This behaviour confuses me. Could someone explain to me why is this happening like this? I expected them to both behave the same.

martineau
  • 119,623
  • 25
  • 170
  • 301
Virgiliu
  • 3,068
  • 6
  • 32
  • 55
  • 2
    http://stackoverflow.com/questions/2017230/why-arent-and-and-or-operators-in-python and numerous others. – S.Lott Oct 12 '10 at 15:01
  • 2
    possible duplicate of ["Boolean" operations in Python (ie: the and/or operators) ](http://stackoverflow.com/questions/3826473/boolean-operations-in-python-ie-the-and-or-operators) – S.Lott Oct 12 '10 at 15:02
  • @SilentGhost: If None is considered the same as False, why does it return None instead of False? Shouldn't an OR applied to two false values return False? – Virgiliu Oct 12 '10 at 18:59
  • 2
    @SilentGhost: I did, I didn't understand and that's why I was asking. – Virgiliu Oct 12 '10 at 20:23
  • 2
    @SilentGhost It is confusing because, apparently, the official docs describe something different than one might expect intuitively from any logical OR operator (i.e. the order of the operands being irrelevant). Behaviour _as documented_ not necessarily implies the _right_ behaviour ... ;-) – Rolf Bartstra Dec 06 '12 at 17:17

6 Answers6

122

The expression x or y evaluates to x if x is true, or y if x is false.

Note that "true" and "false" in the above sentence are talking about "truthiness", not the fixed values True and False. Something that is "true" makes an if statement succeed; something that's "false" makes it fail. "false" values include False, None, 0 and [] (an empty list).

RichieHindle
  • 272,464
  • 47
  • 358
  • 399
  • 6
    LOL, creative application of the recently coined term [truthiness](http://en.wikipedia.org/wiki/Truthiness), but fairly appropriate here, its questionable origins notwithstanding. – martineau Oct 12 '10 at 14:14
  • 7
    @martineau: It's a much older term in this technical sense. Colbert stands a better chance of mainstreaming it than programmers, but he's not the only source. –  Oct 13 '10 at 21:19
  • 2
    Yeah, apparently a *much* older term. On Wiktionary for Etymology they indicate "First attested in 1824". I've never seen in used the technical sense that @RichieHindle did -- although it makes perfect sense in this case. – martineau Oct 13 '10 at 22:17
  • 2
    If '"false" values include False, None, 0 and [] (an empty list)', why then `None != False` evaluates to `True`? – Reloader Jun 28 '14 at 11:24
  • 16
    @Reloader: Just because two values are falsey doesn't mean they are equal. – RichieHindle Jun 28 '14 at 15:14
  • 1
    @Reloader: Set `truthiness = bool`, then `truthiness(None) == truthiness(False)` → `True`. – martineau Aug 28 '21 at 18:42
18

The or operator returns the value of its first operand, if that value is true in the Pythonic boolean sense (aka its "truthiness"), otherwise it returns the value of its second operand, whatever it happens to be. See the subsection titled Boolean operations in the section on Expressions in the current online documentation.

In both your examples, the first operand is considered false, so the value of the second one becomes the result of evaluating the expression.

martineau
  • 119,623
  • 25
  • 170
  • 301
14

EXPLANATION

You must realize that True, False, and None are all singletons in Python, which means that there exist and can only exist one, single instance of a singleton object, hence the name singleton. Also, you can't modify a singleton object because its state is set in stone, if I may use that phrase.

Now, let me explain how those Python singletons are meant to be used.

Let's have a Python object named foo that has a value None, then if foo is not None is saying that foo has a value other than None. This works the same as saying if foo, which is basically if foo == True.

So, not None and True work the same way, as well as None and False.

>>> foo = not None
>>> bool(foo)
True
>>> foo = 5  # Giving an arbitrary value here
>>> bool(foo)
True

>>> foo = None
>>> bool(foo)
False
>>> foo = 5  # Giving an arbitrary value here
>>> bool(foo)
True

The critical thing to realize and be aware of when coding is that when comparing two objects, None needs is, but True and False need ==. Avoid using if foo == None, only use if foo is None. Also, avoid using if foo != None and only use if foo is not None.

WARNING

If you are using if foo or if not foo when the value of foo happens to be None, beware of potential bugs in your code. So, don't check for a potential None value in conditional statements this way. Be on the safe side by checking for it as explained above, i.e., if foo is None or if foo is not None. It is very important to follow best practices shared by Python experts.

REMINDER

True is a 1 and False is a 0.

In the old days of Python, we only had the integer 1 to represent a truthy value and we had the integer 0 to represent a falsy value. However, it is more understandable and human-friendly to say True instead of 1 and it is more understandable and human-friendly to say False instead of 0.

GOOD TO KNOW

The bool type (i.e., values True and False) are a subtype of the int type. So, if you use type hints and you annotate that a function/method returns either an int or a bool (i.e., -> int | bool or -> Union[int, bool]), then mypy (or any other static type checker) won't be able to correctly determine the return type of such a function/method. That's something you need to be aware of. There's no fix for this.

Boštjan Mejak
  • 827
  • 9
  • 23
  • 1
    “In the case of `if foo is not None`, simply do `if foo`”: please note that `if foo` is not the same thing as checking for `None`! The `if` statement converts its expression to `bool` first, so if `foo == 0`, `if foo` will fail. – Norrius Dec 08 '17 at 19:36
  • None or False or 0 are the same thing as logic is conserned. Just stick to the same logic when coding. If you give a variable the starting value of None, stick with checking this value later in the source code with “if foo is None”, but that is basically the same as checking “if not foo”. This is versatile, so use whatever you feel looks best. – Boštjan Mejak Dec 08 '17 at 20:45
  • 2
    I'm just pointing out that this "basically the same" might be a source of subtle bugs. Suppose you have `def fun(foo : str = None): if foo: bar`. Now, what happens when someone passes in an empty string? It might be not the desired result if an empty string is distinct from None in your logic. – Norrius Dec 08 '17 at 21:16
  • When someone passes in an empty string, `None` is returned (since all Python functions return `None` implicitly). – Boštjan Mejak Oct 26 '21 at 14:22
  • 1
    I have fixed my answer. I'm warning of potential bugs when doing `if foo` or `if not foo`. Doing `if foo is not None` or `if foo is None` are expressed as Python's best practice. – Boštjan Mejak Dec 17 '21 at 00:37
6

A closely related topic: Python's or and and short-circuit. In a logical or operation, if any argument is true, then the whole thing will be true and nothing else needs to be evaluated; Python promptly returns that "true" value. If it finishes and nothing was true, it returns the last argument it handled, which will be a "false" value.

and is the opposite, if it sees any false values, it will promptly exit with that "false" value, or if it gets through it all, returns the final "true" value.

>>> 1 or 2 # first value TRUE, second value doesn't matter
1
>>> 1 and 2 # first value TRUE, second value might matter
2
>>> 0 or 0.0 # first value FALSE, second value might matter
0.0
>>> 0 and 0.0 # first value FALSE, second value doesn't matter
0
Nick T
  • 25,754
  • 12
  • 83
  • 121
  • 1
    Strictly speaking, Python does not short-circuit the 'or' and 'and' operations because it is not forced to evaluate to True or False, instead, it returns the arguments, so that the user can the apply the truthiness of the object. In that sense, the answer by RichieHindie is very clear: for or, return the first argument if it evaluates to true, otherwise return the second; for and, it is the convert, return the second if the first evaluates to true, otherwise the first. – Pablo Gutierrez Marques Oct 06 '17 at 16:57
2

From a boolean point of view they both behave the same, both return a value that evaluates to false.

or just "reuses" the values that it is given, returning the left one if that was true and the right one otherwise.

sth
  • 222,467
  • 53
  • 283
  • 367
1
Condition1 or Condition2

if Condition1 is False then evalute and return Condition2. None evalutes to False.

Andrey Gubarev
  • 771
  • 4
  • 6