To start, I’ll give an update on my video series. I’ve recorded my first episode, but I’ve had a ton of troubles when trying to edit it. The application keeps crashing, which is okay, since it recovers most of what I did, but it does grow tedious. I’ve also decided to start the editing over due to a few factors. Lastly, I’ve started recording a series of videos with my best friend for his gaming YouTube channel. All of that together has led me to put off the my video series for a while and get back to writing on the blog. I’ll get back to the video series when I’ve finished recording with my friend. It could take a while.
Python Boolean Operator Confusion
A while back, I stumbled upon a post asking about the how the following lines could possibly right:
'a' == 'b' or 'a' returns 'a'
'a' == 'a' and 'b' returns 'b'
He had a few other lines that did what you might expect, returning True and False. But why do these and and or operators not always return boolean values? To answer that, I’d like to dig into Python’s history.
A History of Boolean in Python
In the beginning, Python didn’t have a boolean type. This may shock you, but Python is actually getting pretty far up there in age, and back when it was created, boolean types weren’t “standard”. Often, 1 and 0 were substitutes for truth and fallacy, respectively. That, coupled with Python’s ability for objects to express “truthiness”, “false” objects were generally representative of “empty” values.
But then PEP 285 came out; True and False were added into the language, but Python still kept its “truthiness” concept. Really, True and False are pretty much (maybe actually) just constant names for 1 and 0.
So, how does this translate to how the earlier lines work?
How the Operators Work
First thing you need to realize (and probably already do) is that and and or are short-circuiting operators, which means they skip doing work that they don’t have to do. To explain, let’s look at the truth tables of the operators:
OR
| a | b | a OR b |
| false | false | false |
| true | false | true |
| false | true | true |
| true | true | true |
AND
| a | b | a AND b |
| false | false | false |
| true | false | false |
| false | true | false |
| true | true | true |
Now, look closely at those tables. In the OR table, any time that a is true, the final result will be true. This means, that when a is true, you don’t even need to find out what b is in order to know the final result. The only time you need to know what b is is when a is false. Interestingly, in both cases, the final result is equal to b. This can be shortened “if a is true, the answer is equal to a; otherwise, it’s equal to b”.
AND has a similar property, but a little different. It can be worded as “if a is false, the answer is equal to a, otherwise it’s equal to b”.
Applying Truthiness
Let’s apply the same idea with truthiness and turn and and or into function definitions:
def and(a, b):
if a: # checks truthiness
return a
else:
return b
def or(a, b):
if not a:
return a
else:
return b
Finally, not takes the result of bool(a) and returns the opposite one.
So, when we see 'a' == 'b' or 'a', we know that it returns 'a' because the left side of or is false, meaning we return the right side. And we know that 'a' == 'a' and 'b' returns 'b' because the left side of and is true, meaning that we again return the right side.
What Good is This?
So what does this do for us? Firstly, it gave Python backwards compatibility to the time before true boolean values. Secondly, it provides ways of quickly setting a default value:
def someFunc(param=None):
param = param or []
…
In this instance, we want the default value for param to be an empty list, but using mutable types like that as the default in the parameter list is dangerous, so we default to None and use that as our falsey value to determine whether something was provided by the caller or not. This isn’t perfect, though. If the caller provides something else that’s falsey, it will be ignored in favor of the default value. This is more properly written with Python’s conditional expression:
param = [] if param is None else param
But there can still be times where the boolean operations could be useful in this way.
Summary
Hopefully you understand how Python does booleans a little better now. Javascript is quite similar in this respect, so don’t think that Python is the odd duck (get it? Because of ‘duck typing’).
Next week, we’ll delve into why 'a' in 'abc' == True returns False.




Pingback: String Python Comparisons Along | Programming Ideas With Jake
Pingback: String Python Comparisons Along – Open Code Group
Pingback: String Python Comparisons Along -
Pingback: String Python Comparisons Along | 神刀安全网
Pingback: String Python Comparisons Along – scribdbook