Day 8: Functions & more midterm 1 practice

back · home · slides · CMSC 201 (Fall 2024) @ UMBC · functions! very cool B)

CMSC 201: Functions and more exam questions

Agenda:

  • HW4 released!
  • "Fun": floating points exposed
  • Who cares? (AKA: what will we make)
  • Introduction to functions!
  • More pratice exam stuff!
  • Goal: Learn about functions, maybe have fun :)

    My email is: sdonahue@umbc.edu (Shane Donahue), office hours Tu/Th ITE 373 2-3PM.

    HW4

    HW4 is out! Due Friday 2024-10-04 at 11:59:59 PM :) You know everything you need to know for it! Don't use functions in HW4.

    Let's look at HW4! (due Oct 4 2024 at 11:59PM)

    The if __name__ == "__main__": convention... You should use it! What does it mean?

    It only makes sense in the context of imported files. When you want to use another person's Python code, you probably don't want to use it all at once, or run whatever testing code they had. You want to take only the bits and pieces you need. So if they had code run when they ran their Python file, you probably don't want to run it when you import it. Don't worry about it too much, but wrap your code like this:

    if __name__ == "__main__":
        # all your code here

    Also, if your code is really convoluted and hard to understand, please add a comment for it :)

    Midterm #1

    Midterm #1 is October 9th for M/W October 10th for Tu/Th! There is no make-up time! Please don't miss it :(! I have no power to give you make-up times. TAs will be in the room, administering the test. It is during the lecture section (so, this time).

    Reminder: If you have SDS accomodations (e.g., extra time or reduced distractions), please book that room and let them know you plan to take the test there! The room here will be very quiet though, so there won't be many auditory distractions.

    "Fun": floating points exposed

    Floating points, or decimal values... how do they work? Why are they so hard to use? Why are they so cursed?

    0.9 + 0.1 == 1.0 # True
    0.2 + 0.1 == 0.3 # ???

    Wonder no more! Amazing site by Bartosz Ciechanowski: float.exposed and accompanying blog post here. Most floats follow a standard: IEEE 754. Long answer short: infinite range, finite bits!

    Who cares (about functions)?

    Everyone cares about functions! I don't even need to convince you. But let's make something fun... Functions let us re-use code and ideas. They can make repetitive code very simple and nice to read.

    Functions

    Functions are one of most important programming concepts. Essentially: take some code and make it re-usable in different situations!

    Functions take some input, and have some output. They are pretty much identical in concept to math functions (like, f(x) = 2x, or y = mx + b). Take some input and produce some output!

    How to write a function

    Here's a function that prints a positive affirmation:

    def print_affirmation():
      print("You are enjoying your computer science 201 course. A lot! >:(")
    
    # Now we "call" the function
    print_affirmation()
    

    Here's one that prints whatever you pass in, plus exclamation marks at the end!

    def make_excited(input_var):
    	print(input_var + "!!!")
    
    make_excited("Hi") # Will print: Hi!!!
    make_excited("I am great today") # Will print: I am great today!!!

    Every time we "call" make_excited, all the code in that function will be executed, then we will continue on from where we called it.

    def is the keyword that defines functions. You already use Python functions without knowing it: print is a function! Python provides many functions to do things you probably want to use.

    We also use a lot of methods, which are functions that act "on" something, like a string. " hello ".strip(), strip is a (string) method. We will only write functions in this class, not methods.

    Challenge: Make a function that outputs the cube root of a number (like a square (to the 2nd power) root, but a cube (to the 3rd power) root).
    def cube_root(num):
    	print(round(num**(1/3))
    
    cube_root(27) # Will print: 3.0

    The values you put into the function definition are called parameters.

        function name
        vvvvvvvvv
    def cube_root(num):
                  ^^^
                  parameter

    The values you actually put into the function are called arguments.

              argument
              vv
    cube_root(27)
    ^^^^^^^^^
    function name

    Functions can return values

    Printing is cool and all, but what if you want to return something from the function? Just like the string methods return a new string, or len() returns the length of a list or string. We can do that!

    def cube_root(num):
    	return round(num**(1/3)) # <-- returns result
    
    print(cube_root(27))

    What will this code print?

    def cube_root(num):
    	return round(num**(1/3))
    
    result = cube_root(27)

    Nothing! It returns the number value, which means you need to assign it to a variable. If you want to actually print your value:

    def cube_root(num):
    	return round(num**(1/3))
    
    result = cube_root(27)
    print("Cube root of 27 is", result)

    You can return multiple values as well, but let's not worry about that for now.

    Challenge: Write a function that takes a temperature and humidity, and returns a string telling you if you should go outside.

    Functions make code easier to read and understand

    We can use functions to decompose the functionality (pun intended) of our code. Let's take our 8 ball code from a while ago:

    import random
    
    fortunes = ["weather is good", "weather is bad", "the weather will be a firestorm", "homework will be easy", "homework will be hard"]
    valid_fortunes = []
    
    user_preference = input("What type of fortune do you want: ")
    
    for f in fortunes:
        if user_preference in f:
            valid_fortunes.append(f)
    
    selected_element = int(random.random() * len(valid_fortunes))
    print("Your fortune is:", valid_fortunes[selected_element])
    

    Let's move the "fortune filtering" into a function. It's kind of noisy being in the middle of our user interaction code.

    import random
    
    def get_valid_fortunes(user_string, fortunes_list):
    	valid_fortunes = []
    	for f in fortunes_list:
    	    if user_preference in f:
    	        valid_fortunes.append(f)
    	return valid_fortunes
    
    fortunes = ["weather is good", "weather is bad", "the weather will be a firestorm", "homework will be easy", "homework will be hard"]
    user_preference = input("What type of fortune do you want: ")
    valid_fortunes = get_valid_fortunes(user_preference, fortunes)
    selected_element = int(random.random() * len(valid_fortunes))
    print("Your fortune is:", valid_fortunes[selected_element])
    

    Now, it's easier to read (hopefully), and we can change the functionality easier. What if we wanted to print three valid fortunes? Or use a different fortune list?

    Functions make code more composable and reusable

    Much like we've seen with strings, functions can be chained, and take other functions as input!

    def cube_root(num):
    	return round(num**(1/3))
    
    print(cube_root(cube_root(19683)))

    Let's re-do our apple censorship program from before, but using functions.

    input_sentence = input("Give sentence: ")
    input_split = input_sentence.split()
    
    for word_index in range(len(input_split)):
        if "apple" in input_split[word_index].lower():
            input_split[word_index] = "banana"
        elif "banana" in input_split[word_index].lower():
            input_split[word_index] = "government-sponsored BANANA(TM)"
    
    print(" ".join(input_split))

    With this code, every time we change how we find a word (using "in", making lowercase, etc), we have to modify each line. Let's make this better using functions!

    input_sentence = input("Give sentence: ")
    input_split = input_sentence.split()
    
    def replace_word(word, find, replace):
        if find in word.lower():
            return replace
        return word
    
    for word_index in range(len(input_split)):
        input_split[word_index] = replace_word(input_split[word_index], "apple", "banana")
        input_split[word_index] = replace_word(input_split[word_index], "banana", "government-sponsored BANANA(TM)")
        input_split[word_index] = replace_word(input_split[word_index], "hate", "love")
        input_split[word_index] = replace_word(input_split[word_index], "worst", "best")
    
    print(" ".join(input_split))

    Much easier 😌

    Exam practice

    Fall 2023 Midterm 1 Study Guide/Answers

    I anticipate the programming free response to be the hardest. I'll have practice problems in future classes, but if you want to practice now, you can speedrun re-solve your homework, or check out the problems on codingbat (https://codingbat.com/python).