3

Can someone explain to me why when evaluating numerical expressions Python as a result of evaluation returns the last thing that was evaluated?

For example:

3 and 5

evaluates to

5

Another question I have is why is it even evaluating these expressions, when I try to check:

3 == True

I get False but when I evaluate:

3 and 5

and get 5 as a result it obviously( I think) thinks that 3 evaluates to True since it wouldn't continue evaluating if it thought otherwise( I might be wrong here). In contrast when I evaluate:

0 and 3

I get 0, what I think is happening is that Python checks whether 0 is True, decides it's not and spits it out.

I'm sorry if it all sounds a bit chaotic but I stumbled across this in my book and was curious if there is something I'm missing.

Blücher
  • 823
  • 3
  • 9
  • 18

3 Answers3

3

Yes, in python any value is either truthy or falsy. Every integer is truthy except for 0. With the boolean operators or and and, python returns the last expression it evaluates, for example 3 or 5 will return 3 as python first sees that 3 is truthy and does not have to evaluate 5 and returns 3.

In 0 and 5, 0 is falsy and so python does not evaluate the next expression and returns 0.

The reason 5 == True gives False as 5 does not equal true, it just acts truthy in boolean expressions. bool(5) == True gives True as this explicitly converts the integer to a boolean.

Andrew Marsh
  • 2,032
  • 15
  • 14
  • No need to talk about "primitive types" (not to mention that they're usually called *built-in*, as "primitive" is associated with limitations and advantages that don't apply to Python). *Every* object has a truth value. –  Nov 20 '11 at 14:59
  • Wasn't sure whether it was possible to have objects that don't have a truth value. – Andrew Marsh Nov 20 '11 at 15:01
  • Well, it seems possible to throw an exception in `__nonzero__` (the method responsible for conversion to boolean), thus aborting execution before a truth value is decided upon, but the default implementation doesn't and sane persons won't do it either. Also, that's arguably just having an undefined truth value, not having noen at all. –  Nov 20 '11 at 15:04
  • @AndrewMarsh , thank you, I can't accept this answer as it didn't address my original question to which I already found the answer. – Blücher Nov 20 '11 at 15:26
  • @AndrewMarsh, it may be possible for objects to not have a truth value: "User-defined objects can customize their truth value by providing a __bool__() method.", so if no such method is defined for an object, evaluating its truth might default to either True or False or it might raise an exception :-). – Dave Nov 20 '11 at 16:01
2

From the Python Reference:

The expression x and y first evaluates x; if x is false, its value is returned;
otherwise, y is evaluated and the resulting value is returned.

If you had said

0 and 5

the value of the first thing evaluated (0) would have been returned.

For the second question, 3 obviously evaluates to true when treated as a boolean, but the == operator does not coerce its arguments to boolean prior to comparison.

Dave
  • 3,834
  • 2
  • 29
  • 44
  • Your last sentence is wrong. `1 == True` and `0 == False` are both `True`. – NullUserException Nov 20 '11 at 15:02
  • 1
    @NullUserException - it's a grey area. There is no coercion of arguments going on in `1 == True`, True *does* evaluate to 1. Try this: `list((x % 2 == 1) for x in range(10))` and you will get `[False, True, False, True, False, True, False, True, False, True]`. Now change `list` to `sum`, and you get 5, because True *does* equal 1 and False equals 0. – PaulMcG Nov 20 '11 at 15:29
  • @PaulMcGuire Doesn't that further prove there *is* coercion, both from int to boolean and from boolean to int? – NullUserException Nov 20 '11 at 15:32
  • 3 == 5 is FALSE, even though 3 and 5 would have had the same boolean value had they been coerced to boolean. The OP's original statement 3==True evaluates to False is correct, surprisingly == coerces to numeric rather than to boolean! 0==True -> False. 1==True -> True. 2==True -> False. 3==True -> False. – Dave Nov 20 '11 at 15:35
  • @NullUserExceptionఠ_ఠ 1.0 == True evaluates to True, 1.1 == True evaluates to False, as do both 0.9 == True and 0.9 == False. So the coercion is not to int, and it's not to boolean either, as I originally said. – Dave Nov 20 '11 at 15:40
  • 1
    @NullUserException - no, it means True and False have the numeric values of 1 and 0. `3 == True` evaluates to False, so there is no coercion. You have to explicitly say you want 3's booleanness, using `bool(3) == True`, which evaluates to True. – PaulMcG Nov 20 '11 at 15:42
0

How boolean operations work

See documentation on boolean operations. They work in the following way:

  • a or b returns the first element that is evaluated as True, so in case of 0 or 3 it will be 3, and in case of 3 or 5 it will be 3 also,
  • a and b returns the first element evaluated as False, otherwise (in case all the elements are evaluated as True) the last element is returned, so 0 and 3 will became 0 and 3 and 5 will became 5,

Solution

But there is a solution to your problem. Just cast the result into boolean using bool():

>>> bool(0 or 3)
True
>>> bool(3 or 5)
True
>>> bool(0 and 3)
False
>>> bool(3 and 5)
True

Did it help?

EDIT:

Another solution

Actually I think in your case there may be even a better solution to your problem. See this:

  • bool(a or b) can be replaced by any([a, b]), and
  • bool(a and b) can be replaced by all([a, b]),

and I now believe this is a more reasonable solution.

Tadeck
  • 132,510
  • 28
  • 152
  • 198