Booleans: Boolean Operators - Lecture

Fred Baptiste
A free video tutorial from Fred Baptiste
Professional Developer and Mathematician
4.8 instructor rating • 4 courses • 31,820 students

Learn more from the full course

Python 3: Deep Dive (Part 1 - Functional)

Variables, Functions and Functional Programming, Closures, Decorators, Modules and Packages

44:37:26 of on-demand video • Updated August 2020

  • An in-depth look at variables, memory, namespaces and scopes
  • A deep dive into Python's memory management and optimizations
  • In-depth understanding and advanced usage of Python's numerical data types (Booleans, Integers, Floats, Decimals, Fractions, Complex Numbers)
  • Advanced Boolean expressions and operators
  • Advanced usage of callables including functions, lambdas and closures
  • Functional programming techniques such as map, reduce, filter, and partials
  • Create advanced decorators, including parametrized decorators, class decorators, and decorator classes
  • Advanced decorator applications such as memoization and single dispatch generic functions
  • Use and understand Python's complex Module and Package system
  • Idiomatic Python and best practices
  • Understand Python's compile-time and run-time and how this affects your code
  • Avoid common pitfalls
English [Auto] High in this video we're going to continue looking at boolean operators but in a little bit more detail in particular we're going to consider boolean operators in the context of truth values. So this does bring back our regular truth table we have these inputs for x and y and then we have the result of X and Y and X or Y. So normally boolean operators are defined to operate on Boolean values and return boolean values. In fact that's called a Boolean algebra and and and or are just operators in that Boolean algebra and that means that these operators are only defined for booleans and will always return a boolean. So for example if we have true or false that will return true we could even use comparisons like this. So in this case one equals to be equals three then a is greater than zero it's true and B is less than 5. That is true and then true and true will return true. So we deal with Boolean inputs and we have boolean outputs. But now consider that every object in Python has a true value. We have this concept of truthiness. And so for any object we really could write the following. We can write bool x and y. That is perfectly legal since X has a truth value we can get the truth value by calling bool on X and we can get the truth value of Y by using bool of y we can do the same thing with or as well. So the thing is that we actually don't have to write bool here. In fact we can just write X and Y or we could write X or Y that will work perfectly well. Python will use the truthfulness of X and the truthiness of y to get our result and to evaluate x and y and x or y. So the question then becomes is what's actually returned. When we write the expression here where x and y are not booleans but just objects that have you know an associated truth then what is being written is that a boolean. And the answer is No. It's not. It's not a boolean. So let's see what's going on. And let's see how Python actually defines it. And and or operators. So let's start with or. And I'll just bring back the truth table for or right here. So x or y is defined this way if X is truthy it will return X otherwise it returns Y. And Bob here is a little puzzled right. What's going on. This isn't kind of the standard thing we think of when we think of the OR operator. It's not a traditional way of teaching it. So it doesn't work as expected with just boolean values. If we just use x and y as booleans does this at least seem to correspond. So it's like look let's just run through all the different options so let's take x and y both false. So the rule is X is false. So we are going return Y because the rule is that if X is truthy we return X otherwise we return y. So X is false. So we return y. Well y 0 in this case. So we get false. Right. And I'm using 0 and 1 as true and false. So if X is true but is false and why is true then X is false so we still return y. So in this case we return 1. And so far we're matching right 0 0 returns 0 0 0 1. We have a 1. So far so good. What about 1 0. Where X is true and Y is false. Well X is true. So we need to return x. And so we return 1. And this still matches our regular truth table. Finally we take both of them equal to true while X is true. So we still return X which means we return TRUE OK. Now one thing to note here is that if you look at what's happening if X is truthy we return X otherwise we return why did you notice that we never actually look at the value of y. We would never do. Right. And if you look at the truth table that kind of makes sense because if X is true. Well we're always going to return true. It doesn't matter what why is now if X is false then we just return why we don't have to do another operation to find the or if X is false. We know that the result is can then be totally dependent on y so a better way to define this in terms of what's actually happening is that if X is truth if we return X otherwise we evaluate Y and return it. And the reason why I want to write it this way is because now you'll notice that we don't actually evaluate Y unless we need to return it. And you remember this whole short circuiting thing we talked about in the last video. That's what's going on. That's y y is not getting evaluated unless it has to. Right. So if the first part of the first operand is true then we just return True but we never evaluate the second part if the first operand is false then we have to evaluate and return. Why. Because Y doesn't have to be a pure number or a pure boolean it could just be an expression could be a function call or something that is you know that returns either a Boolean or an object that has an associated truth value. So that's the reason why we have this definition here and it actually works. It's kind of pretty cool actually. And in fact the all in the and operators return an object they return one of your operands you know either X or Y depending on you know what they were that X is truthy or not. So let's look at and and is defined very much in the same way. But if you think of the end well if the X is false we always return false. If X is true then we have to return y. You'll notice that these 2 0 1 0 1 match here and the 0 0 0 0 0 last year. So if you think about it a little bit you could probably come up with a definition yourself which is if X is false. Return X otherwise return Y. All right. So let's take a look for x and y. If x is falsie return X otherwise return y. So again does this work as expected with Boolean values. So let's take a look let's just run through it very quickly if we have false while X is false. Right. So we return x so our result is false that matches next one if X is false and Y is true while it still doesn't matter we should still return X right. According to this rule and we return 0 which matches what we have in the truth table if X is true and Y is false while X is true. So now we have to return y. So in this case will return 0 which again matches our truth table. And similarly if both are true then because X is true we have to return Y and therefore we return true which is exactly what we have in the truth table. So the checks are as well. Now for the same reason that we discussed with the or why it doesn't actually get evaluated unless it gets written. So again we have the short circuiting because if X is false then we are just going to get false back and this Y will never get evaluated. So our definition really is if X is falsie return x. Otherwise evaluate Y and return it. And again we have the short circuiting and this will then return the object of the operands that we pass in the branch could be booleans which case we get the usual normal results. Or we could pass in any object. So let's look at the consequence of those with the or operator forced. What is a consequence of it. So again just bring back our definition if X is truthy we return x otherwise we evaluate and return y. So again this does both the definition and also handles the short circuiting. So let's take a look at this example here. Let's say that X is none. And why is this string and a then X or Y. Well X is falsie. So we're going to return Y which means we return and a. Similarly if x is an empty string and Y is and a while the empty string is also falsie So we're going to return. And on the other hand if we take X equal to hello and want equal to a. Well in this case halo is a truthy string right a truthy object. So we are going to return x which means we return. Hello. So you'll notice that in both these cases where we had a string that was either none or empty we returned and J. And when I say string we had a variable that was non or an empty string. We returned an A and in the case where our variable was a string with characters we returned the string itself. So if we write something like this eight equals s and a then if S is none we return and if s is an empty string we return. If x is a string with characters we just return s right and we assign that to a. This is basically a way to set up default values for a variable right so we may be dealing with a string of we don't want to have an empty or non variable there so we can do as equals s or an A. And this will ensure that a is always going to be a string. Right. It's always going to be why it's always going to have something in it right. This is making the assumption that s is a string it is pointing to a string. But anyways you get the idea so we can use this for setting up default values. So let's take a look at an example because we can expand this further. We can say equals as 1 or 2 or 3 or 8. And this will then be able be equal to the first truth the value and it's the first roofie value because as we've mentioned before in a case like this we have these multiple or operators. Python will then evaluate them from left to right. Because these are all operators with equal precedence. So we'll will do a left to right evaluation. So essentially it's going to grab the first truth truthy value. And since the last one is always truthy you're insured that is going to be at least an A or it's going to be the first non empty string in as one as tourists. So you can expand that a little further. So that's really handy when you're working with variables and especially if you're pulling data from places that you know you don't really know like maybe a database that could have nullable Springfields or you know Nobel textfield. Or maybe it's from you know an API feed from somewhere. Whatever it is it can be really handy to do things like this. Let's take a look at another example. Let's say we have an integer variable that cannot be zero for some reason or other. We have this integer and we don't want it to be zero and if it is 0 we want to set it to 1. Now obviously you know you could write an IF statement if a is equal equals zero equals 1. You could do something like that or since 0 is a false value we can just write a equals a or 1. It's going to be the same thing it's going to return 1 if a 0 0 is going to return a if is non-zero. So again pretty handy to do. Let's look at some consequences of. And now. And what we can do with it. So again just recall that X and Y if X is faulty we return X otherwise we evaluate and return y. So let's look at this example let's say X has a is an integer a value of 10 and Y is 20 divided by X then X and Y will return Y. Right. Since x is truthy we will return y. We will then evaluate Y which is 20 divided by 2 by 10 which is 2. And that's what gets returned from the x and y. On the other hand let's say that X was zero and Y is also 20 over X then it's going to return 0 because X is false. It's going to return that it will not even try to evaluate 20 divided by x. So it looks like we were able to avoid this division by zero error by using the and operator. And this is a pretty standard way as well we can say X equals a and total divided by 8. Let's say we try to calculate an average where we have maybe a some like total and count the number of samples which is a. And at any point in time you know we could have a count that AB 0. We don't know right. Maybe it's right at the beginning we haven't entered data yet. We're trying to compute the average. Well this will then return a. It will not try to do the division by zero. But if a is greater than zero then it will do the actual computation. So again very handy to have. So as an example if we have equals 10 well 10 and total divided by 10 that's can return total divided by 10. Right but if A is equal to zero then we have zero and total divided by zero. That's going to return 0. OK. So that avoids basically that division by zero error. Ken that's a pretty standard trick that can be used in Python let's take that example with the average that I was talking about. So let's say we have some and so sometimes end is non-zero. Sometimes it is. In either case the average is and and some divide by N because if end is zero we have no count right than the averages zero. So we want to return zero on the other hand if we do have values. So N is non-zero it's going to be some positive integer. Then we do want to take some divided by and that will be the average. Here's another example. Let's say you want to return the first character of a string s or an empty string the string is none are empty. In other words we have a string and we want to bring back the first character of that string. But of course if the string is none or empty We just want to bring back the empty string. So let's see how we could do that. Here's one option if s return s 0. Otherwise return the empty string. Well yeah that will work right. If as is none or if s is a string of length zero. It's going to be falsie right. So it's going to return this empty string here. But if x is a string with characters then its length is greater than zero which means that it's going to be truthy. And we're going to return as 0 option number two which works equally well and actually works maybe well actually works equally well. We can say returned S and S 0. Now that's not option 2 return s n s 0. Well that's kind of OK right. Because if s is none or the empty string then it's going to return s because it's going to be falsie otherwise it will return the first character. So this will not create an error. We won't have an exception this will work just fine in all the cases where X is known as is an empty string or a string of characters. However what is it going to return when S is none right. It doesn't work well with the nut case. It's not going to do what we want we want it to return an empty string. If the string is none here it's going to return number. If S is none. So how can we fix that. Well we can take whatever this returns and we can or it with the empty string so that if the return of this thing here is falsie which means none. All the empty string we're going to replace it with the empty string. So we can do it this way. Return S and S 0 all the empty string. And that will do exactly what we want. In fact you can make the default value not whatever you want. So you can have it all return the first character of the string. Or maybe it returns. And a if you want. If it's an empty or non variable and of course Bob thinks that's really cool. Maybe I do too. But that's kind of a cool way of doing this. It's you know it's a one liner. And once you get used to it it's very easy to recognize this pattern and to understand it and you don't have you know as wordy code as you have over here. So lastly let's look at the boolean not operator. Now the knot is really a built in operator that returns a boolean value so it doesn't work quite the same way as and and or where and and over returning objects right it doesn't do that. It actually returns a you know honest boolean value. So if you do not X then the way it works is that if X is falsie then it will return TRUE right because X is false so we return not false which is true and it will return false the bully and false if X is truthy. So it can still take any object here but the knot will actually return the knot of the truth value of the object. So if we take an empty string for example which is falsie then not an empty string it's an empty list for an empty sequence. Then not this empty sequence will return true. On the other hand if the sequence contains objects it is truthy and therefore not of that will actually evaluate to false. Similarly if none is faulty then not none will be true. So let's go ahead and actually switch to some code and we'll take a look at all of that in action in the next video. So thanks for watching. I'll see you in a bit.