Functions, Loops, and Logic

The core of Python programming is conditional if/else/elif control statements, loops, and functions. These are powerful tools that you must master to solve problems and implement algorithms. Use these materials to practice their syntax. If/else/elif blocks allow your program to make conditional decisions based upon values available at the time the block is executed. Loops allow you to perform a set of operations a set number of times based on a set of conditions. Python has two types of loops: for loops and while loops. For loops work by counting and terminating when the loop has executed the prescribed number of times. While loops work by testing a logical condition, and the loop terminates when the logical condition evaluates to a value of false. Functions are designed to take in a specific set of input values, operate on those values, and then return a set of output results.

Boolean Logic

Truthiness

Evaluating expressions to be True or False will help us control the flow of our program.

cheat sheet

type truthiness
int 0 is False, all other numbers are True (including negative)
containers - list, tuple, set, dict empty containers evaluate to False, containers with items evaluate to True)
None False

We talked about boolean types (True and False) earlier. True and False are keywords in Python, so make sure you don't name your variables the same thing.
>>> True
True
>>> False
False
Sometimes the truth is obvious. For example 3 < 5 is always True. Other times, in Python, the truth value might surprise you. Let's review. First, let's start with an expression we know is always True.
>>> 3 < 5
True
Tip: If you want to test your assumptions about an expression that returns True or False, you can pass it into the constructor for booleans: bool(expression).


Numbers

In Python, the integer 0 is always False, while every other number, including negative numbers, are True. In fact, under the hood, booleans inherit from integers.

>>> bool(0)
False
>>> bool(1)
True
>>> bool(-1)
True


Sequences

Empty sequences in Python always evaluate to False, including empty strings.
>>> bool("")    # String
False
>>> bool([])    # Empty List
False
>>> bool(set()) # Empty Set
False
>>> bool({})    # Empty Dictionary
False
>>> bool(())    # Empty Tuple
False
Sequences with at least one value will evaluate to True.

>>> bool("Hello")   # String
True
>>> bool([1])       # List
True
>>> bool({1})       # Set
True
>>> bool({1: 1})    # Dictionary
True
>>> bool((1,))      # Tuple
True

None

The None type in Python represents nothing. No returned value. It shouldn't come as a surprise that the truthiness of None is False.
>>> bool(None)
False

None is commonly used as a placeholder to mean "I haven't set this value yet". Since empty strings and sequences evaluate to False, we need to be very careful when we're checking if a sequence has been declared or not, or if it's empty. We'll review this concept again when talking about if statements later in the day.
>>> my_name = None
>>> bool(my_name)
False
>>> my_name = ""
>>> bool(my_name)
False

>>> my_list = None
>>> bool(my_list)
False
>>> my_list = []
>>> bool(my_list)
False

Comparisons

How can we compare different values with each other?

Order Comparisons Cheat Sheet


Operator Means
< less-than
<= less-than-or-equal-to
> greater-than
>= greater-than-or-equal-to

In Python, comparing numbers is pretty straight forward.
>>> 1 < 10  # 1 is less than 10? True
True
>>> 20 <= 20  # 20 is less than or equal to 20? True
True
>>> 10 > 1  # 10 is greater than 1? True
True
>>> -1 > 1  # -1 is greater than 1? False
False
>>> 30 >= 30  # 30 is greater than or equal to 30? True
True

Things get interesting when you try to compare strings. Strings are compared lexicographically. That means by the ASCII value of the character. You don't need to know much about ASCII, besides that capital letters come before lower case ones.

Each character in the two strings is checked one by one, until a character is found that is of a different value. That determines the order. Under the hood, this allows Python to sort strings by comparing them to each other.
>>> "T" < "t"  # Upper case letters are "lower" valued.
True
>>> "a" < "b"
True
>>> "bat" < "cat"
True

Equality Cheat Sheet

Operator Means
== equals
!= not-equals

The equality operators val1 == val2 (val1 equals val2) and val1 != val2 (val1 doesn't equal val2) compare the contents of two different values and return a boolean.

Equality works like you'd expect it to for simple data types.
>>> a = 1
>>> b = 1
>>> a == b
True
>>> a != b
False

>>> a = "Nina"
>>> b = "Nina"
>>> a == b
True
>>> a != b
False

Equality for container types is interesting. Even though a and b are two different lists, their contents are still the same. So compared two lists containing the same values with == will return True.

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> a != b
False

Identity Cheat Sheet

Operator Means
is is the same object in memory? (not equality!)
is not is not the same object in memory? (not equality!)

The is keywords tests if the two compared objects are stored in the same memory location. I won't go into too much detail into why, but remember not to use is when what you actually want to check for is equality.

Note: This is something that trips up Python beginners, so make sure you remember that equality (==, !=) is not the same as identity (is, not is).

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]

>>> a ==# Testing for equality. a and b contain the same values
True
>>> a is# Testing for identity. a and b are NOT the same object.
False

Tip: When you're first starting out, the only place you'll want to use the is keyword is to explicitly compare a value to the built-in types of None, True, or False.

>>> a = True
>>> a is True
True

>>> b = False
>>> b is False
True
>>> b is not True   # Opposite of is b True. aka is b False?
True

>>> c = None
>>> c is None
True
>>> c is not None
False

and, or, and not

and, or, and not are the three basic types of boolean operators that are present in math, programming, and database logic.

In other programming languages, you might have seen the concept of and represented with &&, or, represented with ||, and not represented by !. The Python language is instead focused on readability. So we'll use the english and instead of trying to remember fancy symbols. Python still uses the &, | and ! expressions, but they're used for bitwise operations.

You can use them to compare one (or more expressions) and determine if they evaluate to True or False.

Thankfully, you don't have to be a computer scientist to understand them if you use this handy table.

and, or, not Cheat Sheet

Operation Result
a or b if a is False, then b, else a
a and b if a is False, then a, else b
not a if a is False, then True, else False

and

Note: For a and b, if a is false, a is returned. Otherwise b is returned. If a and b are both boolean values, the expression evaluates to True if both a and b are True.

>>> a = True    # a is True
>>> b = True
>>> a and b     # True is returned. (value of b)
True

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

Notice what happens when do the same thing to values that have a "truthiness" to them.

>>> bool(0) # Verify that zero is "falsey"
False
>>> bool(1) # Verify that one is "truthy"
True
>>> 0 and 1 # 0 is False. 0 is returned.
0

or

For a or b, if a is false, b is returned. If a is true, a is returned. a or b evaluates to True if either (or both) of the expressions are true.

>>> True or True
True
>>> True or False
True
>>> False or False
False

>>> 0 or 1      # 0 is false. Return 1.
1

not

a not a
True False
False True

Note:
not a reverses the boolean value of a. If it was true, it will return False. If it was false, it will return True.

>>> not True
False
>>> not False
True

In Combination

When combining multiple boolean operators, you can add optional parentheses for readability. The operations in the inner-most parenthesis are evaluated first.

>>> a = True
>>> b = True
>>> c = False

>>> a and (b or c)
True
You can combine multiple operators to test complex assumptions. For example, to return True only if both values are False, we can use the not negation operation on the result of an or.

>>> a = False
>>> b = False

>>> a or# False because both are False.
False

>>> not (a or b)  # True - checking if both are False.
True