Quiz 1 - Frequently Asked Questions


Style and Format of the Quiz

Will this be Synchronous or Asynchronous and how much time will I have?

The quiz will more of take-home style to ensure time is not a huge pressure. It will be relased on Tuesday 9/29, 4:45 PM Eastern Time and be due at midnight, Tuesday 9/29, 11:59 PM Eastern Time.

International students who opted into the 4:45 AM Eastern Time quizzing will begin theirs via the INTL Gradescope account at 08:45 GMT 9/30/2020 and submit by 4:00 PM GMT.

Am I allowed to use notes, VS Code, and/or the Internet?

Yes to notes, anything on the course site, and VS Code… you are encouraged to try things out in the REPL!

No to using the Internet. While you may think there is no way for us to check whether the Internet was used, it is obvious to tell what methods to program coding were taught in class versus something that was pulled from the Internet. Using obscure methods from the Internet either way will probably get points taken off anyway for not following the conventions we use in class.

And NO to collaboration with other students. As you saw, it is very easy to tell when someone has just changed variable names or move small things around.

Will I need to hand-write anything?

Nope! All done through gradescope/VS Code!

What new topics should I know for the quiz?

  • Anything we previously covered for last quiz (see FAQ for quiz 0!)
  • Using elif statements with if-then
  • Sequences (primary focus on Lists and using range)
  • For in loops
  • Testing functions (will be super helpful when verifying your answers on the quizzes!)

As usual, please take time and practice the syntax for all of these!

What is the breakdown of question styles?

Primarily we will be asking you to apply the concepts from above to come up with function implementations similar to what you have been working on in the exercises and the last quiz.

Using elif

When just talking about if and else, it is the equivalent of a True/False question. Either the condition is true, or it is false, and based off of this, only one of the two paths will run.

if grade >= 60:
                  print("You passed!")
                else:
                  print("Oof")

Think of a typical multiple choice problem with four valid answers. It can only be one of the four given options, right? Once you see an answer that’s correct, you no longer have to consider the rest. The concept is very similar with elif.

What if we had this program be something that decides our letter grade for a class?

if grade >= 90:
                  print("You got an A!")
                if grade >= 80:
                  print("You got a B!")
                if grade >= 70:
                  print("You got a C!")
                if grade >= 60:
                  print("You got a D!")

This would be a wrong way of implementing this. Think about when the user has a grade of 95. All if statements would run, and all conditions would be True since 95 is greater than 90, 80, 70, and 60. Consequentially, the user will end receive that they got an A, B, C, and D - not what you want.

Try this:

if grade >= 90:
                  print("You got an A!")
                elif grade >= 80:
                  print("You got a B!")
                elif grade >= 70:
                  print("You got a C!")
                elif grade >= 60:
                  print("You got a D!")

With elif, we can ensure that every passing grade maps to only ONE letter grade. This is because if one of these statements is true, then the program would not have to worry about any of other conditions in the structure.

If we wanted to add the unfortunate case of failing, adding an elif can be one way of going about this:

# previous code, then:
                elif grade < 60:
                  print("You got an F!")

While this is valid, else is a very effective way in an if-elif structure to just have a “none of the above option” where if all if and elif conditions fail, we know that the else will at least have something to offer! Plus, you don’t have to specify a condition:

# previous code, then:
                else:
                  print("You got an F!")

If you encounter problems where you have a strict choice between multiple options, elif is the way to go!

Sequences

Sequences, while not an explicit data type, is what’s called an abstract data type that we see inherently in actual Python data types.

A sequence is defined as an ordered, indexed set of values. We have already seen this in strings through cipher and the previous quiz! To hold multiple values that are meaningful such as numbers, strings, booleans, etc., we can use tuples and especially lists to hold that data.

Tuples (brief)

Tuples are something we rarely encounter, but it is a way of holding a fixed number of values that can be of any data type! Meaning if I wanted to associate, for example, a student’s name with a grade on an exam (or even multiple if there are fixed number of exams), I can do this through Tuples! Type aliasing can help in defining a more concise way of representing this ‘Tuple type’:

Grades = Tuple[str, float, float]
                
                student1: Grades = ("Amy", 96.5, 88.4)

Lists

One limitation of Tuples is that their length is fixed, meaning we cannot add or remove values if we want. Lists can give us this power to append or pop values from a series of data!

Oftentimes in your functions, you will have to make and return a list. In these situations, you always have to define your empty list first before you go into any looping through ranges or other lists.

To define and initialize an empty list:

<identifier>: List[type] = []
                
                result: List[int] = []

Try to make it a habit to define this empty ‘result’ list where appropriate, and then return that list at the bottom by default if the function is asking you to return a list. This way you at least have something there to either get you started or as a safety net in case points are rewarded for merely returning a list.

Each element of a list can be accessed through indexing, just like how each letter of a string can be accessed. For in loops and ranges make list processing super effective, which you have probably seen in your exercises! We will explain more in depth later about these.

One key thing to note with indexing is that just like with strings, the first element starts at index 0, and the last element starts at the length minus 1, which can be accessed by using the len() function.

A difference with strings and Tuples however comes with the fact that we can actually assign or change each value of an element!

To increment an element by 1, for example:

nums[i] += 1

If we want to insert values at the end of a list (which you will need to know how to do when building and returning a list!):

values.append(110) # Adds 110 to the end of a list called values

To remove unwanted values from a list, we actually will need the index of what we want to remove (or if you don’t specify one, it will remove the last value by default):

values = [ 1, 2, 3, 4, 5 ]
                
                values.pop(1) # Removes value at index 1
                
                print(values) # will print [ 1, 3, 4, 5 ]

Ranges

Ranges are useful whenever we have a natural sequence of numbers, incremented by fixed value every time.

When defining a range, you need to use the range() function that can requires 1 parameter, and two optional ones:

  1. start - optional - inclusive value for where the sequence starts (defaults to 0)
  2. stop - exclusive value for where the sequence stops
  3. step - optional - how much you want to increment each number in the sequence (defaults to 1)
ids = range(0, 4000, 1000) 
                
                print(ids[2]) # prints 2000
                
                count = range(10)
                
                print(count[0]) # prints 0

Ranges typically aren’t widely used, but can certainly be useful when wanting to set counter variables in loops!

We will explain in the for in loop section for how these ranges can be used to iterate through a list!

For in Loops

For in Loops are a form of iteration specifically useful for iterating over a collection of items. This type of loop works well with generally any form of sequence, including tuples, lists, and ranges.

To construct a for in loop, you must specify:

  1. identifier - acts as a variable for the current item in the sequence you are iterating over
  2. sequence - the greater collection of items you are iterating through
# List example:
                
                collection = [1, 2, 3, 4, 5]
                
                for val in collection:
                  # process each val a certain way
                
                # Range example:
                
                ids = range(0, 4000, 1000) 
                
                for id in ids:
                  print (id)  # prints each id in the ids range

When to use them over while

It is generally easier to use a for in loop when you are iterating through a collection of items and processing each item in some way. By using a for in loop, you do not need to define a counter variable as you would with a while loop to access each individual item.

On the other hand, while loops give you more control over the iteration, as you would be able to define the counter variable and change it however you need with each iteration. Or you could specify multiple boolean conditions so you have more constraints on when to loop. This allows for more customizable code.

For example, these two loops do the same thing. Notice how the for in loop both saves code and makes more sense conceptually.

ids = [1, 3, 4, 5, 7]
                
                # While Loop:
                
                index = 0
                while index < len(ids):
                  print(ids[index])
                  index = index + 1
                
                # For In Loop:
                
                for id in ids:
                  print (id) 

Testing your Functions

Testing is extremely helpful in determining how to go about writing a function.

The general workflow of testing:

  1. Create a pytest file as described in his slides that will be the same file name but with ‘test’ attached to the end.

  2. Write a function “skeleton” - Include the function name, parameters, return type, and return a dummy value (i.e. if the return type is int, return 0; if the return type is str, return "")

  3. Write your tests to model how the function would behave if implemented. This includes:

  • At least 2 use cases - cases that would be obvious for the function to return (ex. for a sum function, a potential use case could be sum (1, 3) => 4)

  • At least 1 edge case - cases that would not be as obvious, and would perhaps require additional code to catch and take care of (ex. for a sum function, a potential edge case would be sum (-1, -1) => -2)

  1. Now you can write your function! Keeping in mind your test cases, first write your function so that it satisfies your use cases. Then, modify/add code so that the function satisifes your edge cases as well.

Notes:

  1. Do not forget to import the functions you write into your test file!

  2. Run your tests however you prefer, whether it is typing the python -m command in the terminal or using the testing module feature that VS Code has that makes it easy to just run all your test cases! We will go over how to do this in the video going over the practice problems!

  3. Just because your function passes all of your tests, does not mean it is 100% accurate. Make sure it covers everything!

The Million Dollar Question: How do I best prepare for the quiz?

  1. Review your own notes, focusing on the topics related to the quiz and star/highlight anything you’re unsure about.
  2. Review your assignments and feedback from Gradescope, paying attention to syntax so you do not end up making simple mistakes.
  3. Do the practice exercises that we will assign, since that is essentially what the quiz will ask you to do.
  4. Email TA’s to ask about anything you are unsure about! Office hours will be open Sunday-Tuesday so please come in to ask about anything before the quiz!
  5. Know that this quiz will 100% not be as bad as the last now that you have more time to do the same length of problems!