Exam 2 Review#

Q&A

Q: Are methods just def functions inside classes?
A: Yup - and by beind ddefined inside a class they directly operate only on that class of objects

Q: how would you recommend breaking this down so it doesn’t feel as overwhelming in a single cell? (I tried understanding the code while going through it, but seeing everything all at once made it feel so overwhelming and hard to understand) I know breaking it down piece by piece helps, but is there a way to initially view it as less daunting? A: Understand each component separately - are there any class attributes? any instance attributes? do they require inputs. Create an object and understand the attributes. Then, take each method piece by piece. Add print statements and test out the method as you go. Then move onto the next one. We’ll demonstrate this today.

Q: Does self count as an input parameter when you initialize a new object?
A: It is technically a parameter, but it will never take an input. So we typically only consider the parameters after self.

Q: why do we use brackets instead of {} for the attributes in the for loop of compare
A: We’re indexing into a dictionary. Indexing always requires []

Q: when do you know how to distinguish instance and class attributes
A: If they’re inside an __init__, they’re instance attributes.

Course Announcements

  • CL6 due Fri

  • A4 due Sun

  • E2 is next week

    • sign up if you have not yet!

    • Practice Exam is available - take multiple times!

Day of Exam:#

What to Bring:

  • An ID

  • Your Brain

  • A writing utensil

Reminders:

  • You will put your belongings in a locker; leave time for this

  • You are not allowed to bring in water/coffee

  • They will provide scratch paper & a calculator

  • You’ll need to sign into your PL using your SSO

Location: TTC-CBTF - Applied Physics & Mathematics (AP&M) B349 (basement)

Exam Window: 5/18-5/22 (Mon-Fri); 45min

Exam 2 Plan#

Exam (15 Qs): (there were 25 on E1)

  • Q1 - blank jupyter notebook (no credit)

  • Q2-7 Multiple Choice (6)

  • Q8-13 “Short Answer” (line of code, matching, drop-down, check box) (6)

  • Q14-16 Code Reading & Debugging (3)

Topics Focused on (#Qs):

  1. Loops (6 | 1 MC; 4 SA; 1 Debug)

  2. Methods (2 | 1 MC; 1 SA)

  3. Classes (7 | 4 MC; 1 SA; 2 Debug)

Note: This is the expected layout. Small changes to this could be made.

Topics from E1 (can’t forget)#

  • Variables

  • Operators

  • Functions

  • Conditionals

E2 Topics#

Loops#

Types:

  • for and while

  • range, break, continue

Methods#

  • list, string, and dictionary methods (need to know .append() and .items(); others will be explained)

  • in place vs not in place

# 11AM
# can you go over the items method
my_dictionary = {'a': 1, 'b': 2, 'c': 3}

# using items method
for key, value in my_dictionary.items():
    print(value)

# using indexing
for key in my_dictionary:
    print(my_dictionary[key])
## 11AM & 2PM
# review in place vs not in place

in place - method that changes the thing it’s working on not in place - method does NOT change the thing it’s working on

# append - list method; operates in place
my_list = [1, 2, 3]
my_list.append(4)
my_list
[1, 2, 3, 4]
# upper - string method; not in place; makes things all caps 
my_string = 'good luck on the exam'
new_string = my_string.upper()
my_string
'good luck on the exam'
new_string
'GOOD LUCK ON THE EXAM'

Classes#

  • class

  • class & instance attributes

  • methods

  • self

  • instance

  • accessing attributes

  • executing methods

# 11AM
# instructions; blueprint for creating a Car object - no instance created
class Car():

    # class attribute - true for all instances of Car objects
    num_wheels = 4

    # instance attributes - variables attached to an object; values differ between instances
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
    
    def tell_info(self, color):
        return f"This car is a {self.year} {self.make} {self.model} that is {color}"
        # return "This car is a " + str(self.year) + " " + self.make + " " + self.model
# instance of an object
my_car = Car('Hyundai', 'Santa Fe', 2006)
my_car.num_wheels
my_car.model
my_car.tell_info('black')

Questions#

What questions do you have!?

Practice#

The practice questions below are NOT representative of the typical question on the exam, but are representative of the more difficult questions on the exam. Many students are feeling pretty good about MC & matching questions (and you’ve done lots of those on PL so far) and less confident when there’s less structure. So, I figured if we did these together…we’d get everyone feeling a bit more confident!

The form we’ll use for today (we’ll just keep using the same one….): https://forms.gle/NbSqNnTjRYtKRsUk9

Q1#

Q1. Fix the StudyTracker class below, so that it accomplishes the following:

  • by default sets hours_studied at 0, but allows the user to specify a different value when initializing an instance

  • has a method add_hours that increases the number of hours in the hours attribute by the input to the method

  • has a method study_feedback that returns a different string if you’ve studied less than 1 hour, less than 3 hours, or 3 hours or more. (Note: the strings do not need to be changed, but the conditional logic may)

#original
class StudyTracker:
    def __init__(self):
        hours = 0

    def add_hours(additional_hours):
        hours = additional_hours

    def study_feedback():
        if hours == 1:
            return "Getting started is the hardest part—keep going!"
        elif hours == 3:
            return "Nice! You're building solid study habits."
        else:
            return "Awesome dedication! You're setting yourself up for success!"
#fixed
class StudyTracker():
    def __init__(self, hours_studied=0):
        self.hours = hours_studied
    
    def add_hours(self, additional_hours):
        self.hours += additional_hours

    def study_feedback(self):
        if self.hours < 1:
            return "Getting started is the hardest part—keep going!"
        elif self.hours < 3:
            return "Nice! You're building solid study habits."
        else:
            return "Awesome dedication! You're setting yourself up for success!"

How do I test out a class?

  • Create an instance of the object my_var = ClassName()

  • Look at the values for your attribues my_var.attribute_name

  • Check your methods my_var.method_name()

# TEST IT OUT HERE
hours_zero = StudyTracker()
hours_zero.hours #0
hours_zero.add_hours(0) 
hours_zero.hours #0
hours_zero.study_feedback()
'Getting started is the hardest part—keep going!'
hours_five = StudyTracker(5)
hours_five.hours #5
hours_five.add_hours(6)
hours_five.hours #11
11

Concepts in Q1:

  • classes

  • debugging

Reminder: While studying, you can ask GenAI to:

  • create similar practice problems (and not give the answer)

  • check your work

  • explain the logic without giving you code

  • explain the concepts underlying a given question -> study those concepts

  • explain code

  • Give you a hint when you’re stuck

Q2#

Q2. Below is an attempt at implementing a CoffeeTracker class. Its instance attributes are all working as intended…but buy_coffee is not quite there. Fix the buy_coffee method so that when it takes in a list of prices, it will update the total_spent attribute to:

  • include the sum of all prices in prices

  • update total_coffees attribute to count how many drinks were in the prices list

  • If the number of total_coffees is more than zero, the average_price attribute will be updated, calculating the value in the total_spent attribute divided by the value in the total_coffees attribute. The print statements at the end do NOT need to be changed.

# original
class CoffeeTracker():
    def __init__(self, name):
        self.name = name
        self.total_spent = 0.0
        self.total_coffees = 0
        self.average_price = 0.0

    def buy_coffee(prices):
        total_spent = price
        total_coffees = 1
        
        if total_coffees > 0:
            average_price = total_spent / total_coffees
        
        print(f"{self.name} bought {self.total_coffees} coffees.")
        print(f"Average price per coffee: ${self.average_price:.2f}")
#debugged
class CoffeeTracker:
    def __init__(self, name):
        self.name = name
        self.total_spent = 0.0
        self.total_coffees = 0
        self.average_price = 0.0

    def buy_coffee(self, prices):
        sum_prices = 0
        
        for coffee in prices:
            sum_prices += coffee
            
        self.total_spent = sum_prices
        self.total_coffees = len(prices)
        
        if self.total_coffees > 0:
            self.average_price = self.total_spent / self.total_coffees
        
        print(f"{self.name} bought {self.total_coffees} coffees.")
        print(f"Average price per coffee: ${self.average_price:.2f}")
# Test it out
my_coffee = CoffeeTracker('Josh')
my_coffee.buy_coffee(prices=[5, 5, 5, 5, 5])
print(my_coffee.total_spent) #25
print(my_coffee.total_coffees) #5
print(my_coffee.average_price) #5
Josh bought 5 coffees.
Average price per coffee: $5.00
25
5
5.0
# Test it out
my_coffee = CoffeeTracker('Shannon')
my_coffee.buy_coffee(prices=[5, 7, 8])
print(my_coffee.total_spent) #20
print(my_coffee.total_coffees) #3
print(my_coffee.average_price) #6.67
Shannon bought 3 coffees.
Average price per coffee: $6.67
20
3
6.666666666666667

Concepts in Q2:

  • Classes

  • Debugging

  • loops

  • conditionals

Q3#

Q3a. Assume a fictitious class Exam2 has been defined. It contains:

  • a class attribute course which stores the string ‘COGS 18’

  • two instance attributes storing the name of a student and the score that they earned

  • a single method calculate_percentage that calculates the student’s percentage out of 100 by dividng score by 15

How would you create an instance my_exam2 of this object? How would you access the name attribute? How would you execute the calculate_percentage method?

# YOUR ANSWER HERE
my_exam2 = Exam2('Shannon', 15)
print(my_exam2.name) #'Shannon'
my_exam2.calculate_percentage() # 1 (100)

Q3b Time permitting: Try to write the code for the class described above. Note: You will NOT have to write a whole class from scratch on the exam.

## YOUR CODE HERE
class Exam2():
    course = "COGS 18" 

    def __init__(self, name, score):
        self.name = name
        self.score = score

    def calculate_percentage(self):
        return self.score/15 * 100
my_exam_50 = Exam2(name='Johnny', score=7.5)
print(my_exam_50.name)
my_exam_50.calculate_percentage()
my_exam2 = Exam2('Shannon', 15)
print(my_exam2.name) #'Shannon'
my_exam2.calculate_percentage() # 1 (100)

Q&A#

Q: Are we allowed to use # on the midterm/final project to show thinking (and if we forget to delete before submitting). Like to we get graded on everything in the code or just output (for midterm)
A: Absolutely - leave as many comments as you want throughout; no need to delete

Q: I never know where to begin when you say “test it out here”. any tips?
A: Hopefully the class demo helped, but briefly here: 1) create an instance of your object; store it in a variable; 2) using that variable, check the values stored in your attributes - do they meet expectation?; 3) call your methods on that variable - does the output make sense? should any attribute’s values have been udpated - if so, are they?