COMP1701-004

fall 2023

lec-09

about these slides...

Looking Ahead

A3?

RECALL

def undo(x):
    print("undoing....")


def vamp_in_the_middle(left: str, right: str) -> None:
    return f'{left}vamp{right}'


def lazy_and_rude(something):
    flip(something)
    print(something)


def flip(invert_this: int) -> int:
    return -1 * abs(invert_this)


def proclaim() -> None:
    print("yea, verily!")


def main():
    input("Yes or no: this is pointless? ")
    s = vamp_in_the_middle("make my", "bed")
    lazy_and_rude(4)
    undo(s)


main()
  1. Name all the void functions.
  2. Which functions return something?
  3. How many function calls are there?
  4. How many arguments altogether?
  5. How many parameters altogether?
  6. How many function definitions?

In this script...

let's talk about these  things today:

 the boolean type, variables

 comparison operators

 naming boolean variables

 logical operators

SO BOOL!

boolean type & variables

boolean type & variables

what types have we used so far?

  1. int        (like 4, 0, -1_532_873)
  2. float    (like 5.12, 0.0, -153.00012)
  3. string  (like "foo", 'bar', f"{12:10}")

boolean type & variables

meet the bool type - unlike its cousins, it only has 2 possible values!

True
False

and

careful with those caps, folks!

# REPL time!

type(True) # type() is useful!
type(False)
type(true) # whoops!
type(F) # nope
type("True") # careful now
type(bool("False")) # yay?

put type() in your toolkit

type(bool("False")) # yay?

Here there be dragons.

Life isn't as rosy as you think.

# predict these

bool("True")
bool("False") # wait...what?
bool("Argle Bargle Snargle") # ???
bool(" ") 
bool("")
bool(0)
bool(1)
bool(153.12)

Takeaway:
Be careful using bool()!

btw...why "bool"?

Meet George.

George Boole.

“Boolean algebra has been fundamental in the development of digital electronics, and is provided for in all modern programming languages.”

Way to go, George!

boolean type & variables

- Wikipedia

Just like we can store ints, floats, and strings in variables...

boolean type & variables

# int variables
num_pie_pieces = 17
length_of_name = len("JP")  # 2, since 2 characters

# float variables
anger_buildup_rate = 89123.99
area_of_circle = round(math.pi * 7, 2)

# string variables
user_name = "Ms. Bindersmoot" 
greeting = f'Why, hi there, {user_name}!' # 'Why, hi there, Ms. Bindersmoot!'

...we can store bools in variables, too.

# bool variables
has_weak_heart = False
is_screaming = "STOP SHOUTING!".isupper()  # huh...that's new
is_boolean = type(has_weak_heart) is bool  # huh...that's new, too!

comparison operators

comparison operators

What operators have we used so far?

  1. assignment  (=)
  2. math             (like +, -, //, %, *, /, **)
  3. string            (like +, *)

comparison operators

Meet the comparison operators - they do what their name suggests: compare 2 things

Grade 12 Python
> >
< <
>=
<=
= ==
!=

careful!!!

Let's kick some tires on these operators with some ints

# REPL time!

4 > 3 # True
-1 > 0 # False

-8 < 1 # True
1 < 1 # False

8 >= 8 # True
100 >= 1000 # False

(6 + 2) <= 8 # True
-4 <= -5 # False

100 == (2 * 50) # True
0 == "0" #False

4 != 3 # True
1_789 != 1789 # False
Grade 12 Python
> >
< <
>=
<=
= ==
!=

Careful - working with negatives hurts the brain.

Evaluate bracketed expression first

# REPL time!

"a" < "b"   # True
'Z' >= 'A'  # True
"Z" < "a"   # sayWHATnow?!?!

"apple" == "apple"  # True
"apple" == "Apple"  # oh, great

'I am a wild party' != 'I am a wild party' # False
"" != " " # Careful there...

Moral of the story: string comparisons kinda work like you expect, with some gotchas.

Let's try these operators with some strings

comparison operators

We don't talk about Bruno floats

(0.1 + 0.2) == 0.3 # True?
(0.3 * 3) + 0.1 == 1.0 # True?

🙋🏻‍♂️❓🙋🏻‍♀️How is data represented in memory?

Takeaway:
Avoid using comparison operators with floats.

This being said, you'll still see float comparisons being used out there...including in labs, on tests, in assignments....

comparison operators

Since the results of comparisons are bools, we can store them in variables!

# REPL time!

statement = "K"
confusingly_short = len(statement) < 2

temp_in_c = 99
is_boiling = temp_in_c >= 100

response = input("Continue? ")
wants_to_continue = response == "Y"

comparison operators

now you try

a = 7 >= 8
b = (3 + 4) < (8 - 1)
c = "pear" >= "pear"
d = len("foo") != 3
e = (8 % 4) == (2 // 3)

What values are in a through e?

naming boolean variables

naming boolean variables

best practices for naming your boolean variables (or your "bool vars", as the cool kids would say)

JP's rule of thumb:
If you can say "If [your variable]" and it sounds kind of Englishy, you're OK!"

valid_input
input

"if valid input..."

"if input..."

is_valid_input

"if is valid input..."

maybe a bit off?

logical operators

WARNING
this section is gonna be long

logical operators

Meet the logical operators - they only work with boolean expressions (things that evaluate to True or False) 

operator example description
and x and y True only if
x AND y are both True
or x or y True as long as at least ONE of x and y is True
not not x The inverse of x.
(not True == False)
(not False == True)

logical operators

Let's meet and 

# let's use the debugger here

some_text = "ARRRRRRG"
very_screamy = len(some_text) > 2 and some_text.isupper()  # T and T => T

some_text = "AR"
very_screamy = len(some_text) > 2 and some_text.isupper()  # F and T => F

some_text = "ARRrrrrg"
very_screamy = len(some_text) > 2 and some_text.isupper()  # T and F => F

some_text = "a"
very_screamy = len(some_text) > 2 and some_text.isupper()  # F and F => F

🙋🏻‍♂️❓🙋🏻‍♀️There's an important pattern here - do you see it?

isupper() tells you weather a given string is ALL IN UPPERCASE. Note how it's called!  <<<

Let's meet or 

# let's use the debugger here

energy_level = 3
hungry = True
should_take_break = energy_level <= 3 or hungry # T or T => T

energy_level = 3
hungry = False
should_take_break = energy_level <= 3 or hungry # T or F => T

energy_level = 15
hungry = True
should_take_break = energy_level <= 3 or hungry # F or T => T

energy_level = 59
hungry = False
should_take_break = energy_level <= 3 or hungry # F or F => F

🙋🏻‍♂️❓🙋🏻‍♀️There's an important pattern here - do you see it?

logical operators

Let's meet not 

# REPL time

wind_speed = 80
windmill_turning = not (wind_speed <= 20)  # not F => T

wind_speed = 20
windmill_turning = not (wind_speed <= 20)  # not T => F

unary operator (because it only takes ONE operand)

logical operators

not can hurt 

# REPL time

wind_speed = 80
windmill_turning = not (wind_speed <= 20)  # ow

wind_speed = 20
windmill_turning = not (wind_speed <= 20)  # ow
# REPL time

wind_speed = 80
windmill_turning = wind_speed > 20  # ah...

wind_speed = 20
windmill_turning = wind_speed > 20  # ...much better!

Takeaway:
Avoid using not - if you can.

Flip the operators!

logical operators

compound expressions

take_umbrella = (raining and not driving) or i_like_umbrellas   
valid_e = (e < 10 and e * 4 >= 20) or e == -1   

life gets "interesting" when we start making more complicated expressions out of all of these conditional and logical operators

logical operators

compound expressions

busy = True
sleepy = True

ok_to_take_nap = not busy and sleepy

let's try one

1. evaluate any boolean variables / expressions

ok_to_take_nap = not True and True

3. evaluate result

2. flip any nots to make it hurt less

ok_to_take_nap = False
ok_to_take_nap = False and True

Remember:
If you use
and, if either operand is False, the result is False

compound expressions

hunger_level = 4
food_spoiled_probability = 0.3
im_a_rat = False

eat_it = (hunger_level > 3 and not food_spoiled_probability > 0.5) or im_a_rat

let's try a harder one

1. evaluate any boolean variables / expressions

3. simplify

eat_it = (True and not False) or False

2. flip any nots to make it hurt less

eat_it = (True and True) or False
eat_it = True or False

4. evaluate result

eat_it = True

Remember:
If you use
or, if either operand is True, the result is True

compound expressions

x = 3
y = 0

grrr = x == 1 or x != 3 and not x == y and not y > 1

let's try an even harder one

1. evaluate any boolean variables / expressions

grrr = False or False and not False and not False

2. flip any nots to make it hurt less

grrr = False or False and True and True

Uh oh. No brackets to guide us here.

grrr = (False or False) and (True and True)  ???
grrr = False or (False and (True and True)) ???
grrr = ((False or False) and True) and True ???

order of operations​ 

if you don't have brackets to guide you, you need to know NAO: not > and > or

1. nots first, left to right

2. ands next, left to right

3. ors next, left to right

We've already been doing this.

compound expressions

x = 3
y = 0

grrr = x == 1 or x != 3 and not x == y and not y > 1

pick up where we left off

2. flip any nots to make it hurt less

grrr = False or False and True and True

3. bracket ands left-to-right

grrr = False or ((False and True)and True)

4. simplify

grrr = False or (False and True)
grrr = False or False

5. evaluate result

grrr = False

logical operators

Naturally, YOU will be nice and not cause suffering like this, right?

Bracket expressions to avoid confusion.

Better yet, avoid making these kind of complex expressions in the first place!

logical operators

compound expressions

e = 4
valid_e = (e < 10 and e * 4 >= 20) or e == -1  

One more. Need to make sure you're still alive.

1. evaluate any boolean variables / expressions

valid_e = (True and False) or False 

2. simplify

valid_e = False or False 

3. evaluate result

valid_e = False

logical operators

keep an eye out for this pattern

not(k >= 0 and k <= 99)
not(speed < 4 or in_control)

When you not a compound expression using and/or, you can use De Morgan's Laws

not(k >= 0 and k <= 99) 
not(speed < 4 or in_control)
(k < 0 or k > 99) 
(speed >= 4 and not in_control)

logical operators

now you try

ok = not(k >= 0 and k <= 99)

What value will ok have if k is 7? How about 100?

logical operators

now you try

CUTOFF = 100
will_buy = price <= CUTOFF or not(cash < price or out_of_print)

What value will will_buy have if
  - price is 100
  - cash = 10
  - out_of_print = True

logical operators

short-circuit evaluation

CUTOFF = 100
will_buy = price <= CUTOFF or not(cash < price or out_of_print)

What value will will_buy have if
  - price is 100
  - cash = 10
  - out_of_print = True

Something interesting happened here...did you notice it?

True
Something

But True or ANYTHING is True!

So Python - and you - don't even need to figure out what Something is -
just evaluate the right-hand side of the assignment to True!

This "shortcutting" is called short-circuit evaluation.

logical operators

short-circuit evaluation

can_continue = not(energy == 0 or shield == 0) and not hull_breached 

What value will can_continue have if
  - energy is 0
  - shield = 100
  - hull_breached = False

Another example (with and this time).

True
Something

Short-circuiting happens twice here!

False
Something

WARNING about short-circuit evals

logical operators

now you try

a = not x > 5 or y < 20 and x + y > 10
b = x <= 5 and not y - 1 > 1 or y == x and x - y != 5 

What value will a and b have if x is 5 and y is 10?

Re-write the right-hand sides of the assignment statements, removing the nots and adding brackets, to make the precedences explicit!

if you have any brain-juice left

RECAP RECAP

What did we talk about?

lec-09

By Jordan Pratt

lec-09

boolean types, variables | comparison operators | logical operators | boolean variable naming

  • 254