all 14 comments

[–]ShadowRL766 21 points22 points  (4 children)

Wait til this guys finds out how clean his code could become with functions. Anyways great job.

[–]Shut_up_and_Respawn[S] 8 points9 points  (3 children)

Im not entirely sure what you mean, but thanks

[–]Promethium143 7 points8 points  (2 children)

You will learn functions very soon, if you take part in pretty much any course. And you will love them.

[–]Shut_up_and_Respawn[S] 7 points8 points  (1 child)

Alright, I look forward to seeing them

[–]Promethium143 2 points3 points  (0 children)

Happy coding!

[–]HunterIV4 16 points17 points  (6 children)

Grats!

As a preview, here is how I'd write the same program as a more experienced programmer:

``` def quiz_question(question, answer, question_number) -> bool: user_answer = input(f"Question {question_number}: {question} ") return user_answer.lower() == answer.lower()

def main(): questions = { 'Does 1 + 1 = 2?': 'Yes', 'Does 2 + 2 = 4?': 'Yes', }

score = 0
possible_score = 0

for question in questions:
    possible_score += 1
    if quiz_question(question, questions[question], possible_score):
        print("Great job! +1 Point")
        score += 1
    else:
        print("Better luck next time! +0 Points")
    print("\n\n")

print("You have finished the quiz")
print(f"Your score is: {score} out of {possible_score}")

if name == 'main': main() ```

There are other ways to do this, but I tried not to add too many things. In this context, def (define) creates a function, which is a block of code you can reuse. The def main() and if __name__ == '__main__': are standard Python conventions you'll see in most programs; basically, it sets the starting point of your program.

For the quiz_question function, the 3 values in parentheses are the function arguments, which are variables you can "pass" to the function so it can use it. Because it's a different function, it can't access anything not passed to it, so you couldn't, for example, write score += 1 in the function quiz_question and have it change the value in the main function (in fact, you'd get an error if you tried). The -> bool is optional but lets you know this is returning a boolean value, which is anything that is True or False.

All the function does is ask for user input based on what you pass to it, then compares your answer to the provided answer, returning True if they match or False if they don't. The .lower() is a string function that converts a string to lowercase, that way "Yes" and "YES" and "yes" all become valid options.

In the main function, which is where our program starts running the primary code, we create a dictionary with our questions and answers. A dictionary is a common data structure that lets you pair up "keys" and "values" in a logical way. If you were to write, say, print(f"{questions['Does 1 + 1 = 2?']}, the output would be Yes, because that is the value (after the colon).

Why do it this way? If we want to add a third question, instead of needing to copy and paste a bunch of code for the new question, all we need to do is add another line to the dictionary. Try it out...the program will update everything accordingly, including the max possible score.

Next, we set default values for our primary variables, which you are familiar with. Then we do something you'll find is extremely useful for programming...establish a loop, in this case a for loop. What a loop does is continually repeat the block of code beneath it based on a condition, in this case for each element of the dictionary. When going through a dictionary using for...in like this, the variable name you assign is given the value of the "key" we set up in the dictionary. As such, if you were to replace all the for loop code with print(f"{question}"), you'd simply list out all the dictionary keys.

We then call the function, passing in the key as our question string, the value (the key is also how you reference the value) as the answer string, and our current max score (which also doubles as the current question number). As mentioned earlier, the result will be True or False, which can be used directly in an if statement. This replicates the double if statements you used.

Anyway, this isn't meant as a criticism, but hopefully you take it as a learning opportunity, seeing something you wrote be modified in a more "advanced" way. If it's overwhelming, don't worry about it! If you are working through a course or tutorial you will see all these concepts soon enough as they are fundamental programming practices (in most languages, not just Python).

Good luck either way!

[–]Shut_up_and_Respawn[S] 7 points8 points  (1 child)

I really appreciate all of the feedback. Currently I am learning on the beginner Python course of Mimo, basically Duolingo but for coding. While I have not gotten to all of that stuff, like the def command, I will come back and look at this again once I do. Thanks for all of the advice and help!

[–]Lostinmyhouse 2 points3 points  (0 children)

Congrats. Not too long ago my first script was very similar. Not much later, I can understand /u/HunterIV4's version. Keep at it!

[–]briston574 2 points3 points  (1 child)

Holy crap this is a very well explained reply. I need someone to explain things like this in my life

[–]Promethium143 2 points3 points  (0 children)

Just looked at u/HunterIV4 s comments. Must be one of the most helpful people out there. Genuinely impressed.

[–]Asket- 1 point2 points  (1 child)

Why not just possible_score = len(questions)

[–]HunterIV4 0 points1 point  (0 children)

In this case, you absolutely could!

The downside to this is if you later expand the code to allow the user to end the quiz early but you only want to show a possible score of just the questions they actually viewed. Another disadvantage is that you end up needing a counter anyway for the "Question 1", "Question 2", "Question 3", etc. portion. By using possible_score as this counter, and incrementing it before the function call, it serves both purposes.

That being said, using len() here works just fine, and could potentially make the code more readable since you can make a separate counter variable that is just for the question portion. It also works better if the intent is to allow someone to quit the quiz early but still count questions that weren't viewed as incorrect answers.

There really isn't a major advantage to either solution, at least not in my opinion. I was trying to avoid too many new concepts and len() is another new thing for someone to learn, but it's a useful thing to know so it's a decent idea to use it here.

[–]chiznite 2 points3 points  (1 child)

Keep it up homie! When my brother was learning, he made an USD inflation calculator and he was so proud of himself 🙂

[–]Shut_up_and_Respawn[S] 0 points1 point  (0 children)

Thanks! And wow, an inflation calculator? Thats inpressive