Ovi
Ovi

Reputation: 573

Need help understanding Booleans?

I am reading about booleans in my book, and it says:

x and y------------If x is false, return x. Otherwise, return y.

x or y--------------If x is true, return x. Otherwise, return y.

This doesn't make sense to me from the everyday usage of "or" and "and" To me, it would make sense if it said:

x and y------------If x is false, do nothing. If y is false, do nothing. If x and y are true, return x and y

x or y--------------If x is true, return x. If x is false, check y. If y is false, do nothing. If y is true, return y

Do I just need to blindly accept the actual definitions, or can I understand them because they actually make sense.

Upvotes: 0

Views: 157

Answers (8)

krethika
krethika

Reputation: 4476

The behavior may seem strange, but consider the following hypothetical examples. Starting with something obvious,

>>> True and False
False
>>> False and True
False

this is really easy to understand since we're dealing with boolean values. Remember this example, because every other example can be thought of this way.

Now consider if the and and or operators were to convert every object to a boolean before comparing. For example, an empty string or empty list would be False, and non-empty ones would be True. It would look like this (obviously this is not what it ACTUALLY looks like)

>>> "vanilla" and ""
False
>>> "" and "vanilla"
False

This makes perfect sense. After all bool("vanilla") and bool("") would be the same as True and False which we already know is False

Instead of actually converting them to True or False, though, it can do the comparison without ever converting them. As a result, you don't really need it to return True or False. It can just return the actual object it tested.

>>> "vanilla" and ""
""
>>> "" and "vanilla"
""

For truth testing purposes, returning "" is the same as returning False, so there's no need to convert it to a boolean. That's why it always returns an object whose truth value is the same as the result of the operator.

Upvotes: 1

Lottamus
Lottamus

Reputation: 457

Its probably easier if you think about it in each literal case

x and y------------If x is false, return x. Otherwise, return y.

x or y--------------If x is true, return x. Otherwise, return y.


CASE 1: x = true, y = true

"if x is false, return x. Otherwise, return y."

Then this will return y which is true. This makes sense because x and y are both true.

(true and true == true)

"If x is true, return x. Otherwise, return y."

The this will return x which is true. This makes sense because one of x or y is true.

(true or true == true)


CASE 2: x = false, y = true

"if x is false, return x. Otherwise, return y."

Then this will return x which is false. This makes sense because x and y are not both true.

(false and true == false)

"If x is true, return x. Otherwise, return y." The this will return y. This makes sense because one of x or y is true.

(false or true == true)


CASE 3: x = true, y = false

"if x is false, return x. Otherwise, return y."

Then this will return y which is false. This makes sense because x and y are not both true.

(true and false == false)

"If x is true, return x. Otherwise, return y."

Then this will return x which is true. This makes sense because x or y is true

(true or false == true)


CASE 4: x = false, y = false

"if x is false, return x. Otherwise, return y."

Then this will return x which is false. This makes sense because x and y are not both true.

(false and false == false)

"If x is true, return x. Otherwise, return y."

The this will return y which is false. This makes sense because neither x nor y is true.

(false or false == false)

Upvotes: 0

Barmar
Barmar

Reputation: 780673

Many (most?) programming languages, including Python, implement short-circuiting in their boolean operators and and or. So they evaluate their operands from left to right, and stop as soon as the final result can be determined.

Since x and y and z and ... is guaranteed be false if any operand is false, it stops evaluating the operands as soon as it encounters a false one. And x or y or z or ... is guaranteed to be true if any operand is true, so it stops as soon as it reaches a true operand. In either case, if they make it all the way to the last operand, they return its value.

In some languages, the boolean operators just return a strict boolean result, either true or false (in some languages these are represented as 1 and 0). But in Python (and some others, such as Javascript and Common Lisp), they return the value of the last operand that was evaluated, which determined the final result. This is often more useful than just the truth value of the expression.

When you put these features together, it allows some succinct idioms, e.g.

quotient = b != 0 && a/b

instead of

if b != 0:
    quotient = false
else:
    quotient = a/b

Upvotes: 1

bentup
bentup

Reputation: 51

While the book presents it in a slightly confusing way, it is correct. Boolean logic must evaluate to either true or false.

For X and Y in order to return true they both must be true, if X is false then it returns false. If X is true then it returns Y which is either true or false and also the correct answer.

For X or Y to return false they both must be false. If X is true then it can return true (X). If X is false then it returns whatever the value of Y is.

Upvotes: 1

Blair
Blair

Reputation: 6693

Your book is right - see the documentation. It might be unintuitive at first, but this behavior (called short-circuiting) is extremely useful. In a simple case, it allows you to save a lot of time when checking certain conditions. In this example, where function f takes 10 seconds to evaluate, you can definitely see one use:

if f(foo) or f(bar) or f(baz):

If f(foo) is True, then there is no need to evaluate f(bar) or f(baz), as the whole if statement will be True. Those values are unnecessary and you'll just be wasting your time computing them.

Another extremely common use of this behavior is in null (or for python None) checking. It allows safe usage of functions all within one line:

if obj != None and obj.foo():

If obj is None, the if statement is guaranteed to be False, and so there is no need to check (or even evaluate) obj.foo(), which is good, since that would cause an exception.

Short-circuiting is very common in many programming languages, and is very useful once you fully understand how to use it.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599470

The first set of descriptions are shortcuts: following these will give you exactly the same results as the "usual definitions" of true and false.

But your own descriptions don't make much sense. You can't "do nothing"; you have to return some value from a comparison, either true or false. And you can't return both a and b, either: again, the result of a boolean comparison must be a boolean, not a pair of booleans.

Upvotes: 0

skytreader
skytreader

Reputation: 11697

Unlike some other languages, you can use any object as operands of boolean operations. All your books says is that you can use boolean operators as a quick "filter" of values.

For instance, say you want to choose a non-empty list between two lists. The following is a valid (and more Pythonic) way to do it:

>>> [] or ['something', 'here']
['something', 'here']

Contrast to (not making use of Python idioms in Python):

if len(l1) != 0:
  return l1
else:
  return l2

Upvotes: 1

Lee Daniel Crocker
Lee Daniel Crocker

Reputation: 13171

"Do nothing" isn't an option. The mathematical expression x or y must have a value (which is true if either x, y, or both is true). And x and y must have a value (which is true if and only if x and y are both true).

The way your book defines them is mathematically correct, but confusing (until you get into things like short-circuit evaluation).

Upvotes: 4

Related Questions