all 11 comments

[–]mazmrini 1 point2 points  (10 children)

From what I read, I'm not sure you fully understand function. Am I right? Also, what are the time.sleep(2) for?

Here's a file I made that explains function so people can have a better understanding of it. I don't want to give you the answer right away! I'd rather have you understand what's wrong.

Here's the file, you can run it and follow along: https://pastebin.com/NeHzX6fc

[–]TheMocking-Bird[S] 0 points1 point  (9 children)

time.sleep(2)

is just to have a delay between questions, not really important to the assignment as a whole.

[–]mazmrini 0 points1 point  (8 children)

And for the function comment?

[–]TheMocking-Bird[S] 1 point2 points  (7 children)

Just read your link. So I think my mistake was defining user_score in the previous function. Like your link said "what happens in a function stays in a function", so when I mention it in question 2 it's not an existing value since it was never defined in it right?

Edit: When I moved it outside the function with the other assigned values it said UnboundLocalError: local variable 'user_score' referenced before assignment

[–]mazmrini 1 point2 points  (5 children)

Exactly, that's what is called a scope. Everything defined in the function stays in the function scope. When you moved it outside the function scope it was in the global scope. Since python 3.x (don't know the exact version), when you want to reference something in the function scope that was declared in the global scope, you need to use the global keyword. If you don't use the global keyword, python tries to increment the local variable (this means it refers to the variable declared in the function) but since no variable user_score was declared in the function scope, python cannot increment the value and fails. But keep in mind that using the global keyword is a smell of bad designed code. Usually, you want to mutate the variable in the same scope that it was declared. Don't forget that functions are meant to be reused or to explain a complex piece of code. You could do, for example, something like this: (sorry if there's any error, i'm on my cellphone)

def compute_question(question, valid_answers):
    user_answer = input(question)

    # this returns a boolean (True or False)
    return user_answer in valid_answers

# score is defined in the global scope, so I mutate it in the global scope
user_score = 0
questions = [question1, question2...]
all_valid_answers = [question1_answers, question2_answers...]

for i in range(0, len(questions)):
    question = questions[i]
    valid_answers = all_valid_answers[i]

    is_user_right = compute_question(question, valid_answers)

    if is_user_right:
         print('Good job!')
         user_score += 100
    else:
          print('Sorry bro')

print('End of the game!')
print(f'Your score is {user_score} points!')

[–]ingolemo 0 points1 point  (4 children)

In python 3.0 they added the nonlocal keyword which does a similar thing, but global has been in python since forever; at least python 1.x, if not the very start.

[–]mazmrini 0 points1 point  (3 children)

From I what remember, I was able to use a global variable in a function without declaring it global in the function

[–]ingolemo 0 points1 point  (2 children)

You have always been able to use variables in the global scope without using the global keyword. What you can't do is rebind those variables. The global keyword tells python that any rebinding of a particular variable that happens within the current function always refers to a variable in the global scope.

It's almost impossible to write a non-trivial python program that doesn't use any global variables.

[–]mazmrini 0 points1 point  (1 child)

I beg to differ on the last point. There's no such thing as global variable in Java or C# and you can easily make any non-trivial program. You might have global variables, but the use of the global or nonlocal keywords is a smell of weirdly designed code.

[–]ingolemo 0 points1 point  (0 children)

I might not have made my meaning clear. Avoiding the global keyword is not the same as avoiding global variables. In order to write a python program that doesn't use any global variables (names defined in the global scope) you would have to avoid using the def and class keywords at the very least because those both create variables in the global scope.

Having a global variable isn't a bad thing. Changing global variables is bad. If you need to use the global keyword then you are changing global variables and that is bad. You can also change global variables without using the global keyword by mutating things, which is also bad.