Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Basics (2015) Number Game App Number Game Introduction

tried creating function to hold "get secret number" logic, keep running into NameError

After the last lesson finishing with the advice around cleanup and extensibility, I attempted to create functions to store each of the pieces of logic in the number_game exercise.

If you put the logic to get the secret number in it's own function, how do you invoke that function in such a way that the secret number is available to the logic that requires it in the game loop?

Here is the code I've created for this:

# generate a random number between 1 and 10
def choose_secret_number():
    secret_number = random.randint(1,10)

# get a number guess from the player
def game():
    while True:
        player_guess = int(input("Guess a number between 1 and 10: "))
        if player_guess == secret_number:
            print("you got it! My number was {}.".format(secret_number))
            break
        else:
            print("guess again")

#secret_number = random.randint(1,10)
choose_secret_number()
game()

However, when I try to execute the file, that function call fails (silently), game() is invoked and I am prompted for the first guess, but upon entering it I get the following error output:

File "number_game.py", line 19, in <module>                          
    game()                                                             
  File "number_game.py", line 11, in game                              
    if player_guess == secret_number:                                  
NameError: name 'secret_number' is not defined

For the life of me, I can't understand why the variable secret_number is not defined when the random.randint() logic is inside a function. If I remove the function, execute the following, it works perfectly:

def game():
    while True:
        player_guess = int(input("Guess a number between 1 and 10: "))
        if player_guess == secret_number:
            print("you got it! My number was {}.".format(secret_number))
            break
        else:
            print("guess again")

secret_number = random.randint(1,10)
game()

I'm sure this is just something to do with functions that we've either not learned yet, or I glossed over and forgot. Any help is appreciated.

2 Answers

andren
andren
28,558 Points

This is an issue of variable scoping. When you define a variable within a function that variable will only exist within said function, it cannot be accessed outside of it.

The normal way this issue is dealt with is that a function returns the value it has worked on so that it can be accessed outside the function.

For example your code could be rewritten like this:

import random
# generate a random number between 1 and 10
def choose_secret_number():
    return random.randint(1,10) # Return the random number

# get a number guess from the player
def game():
    secret_number = choose_secret_number() # Take the number returned and assign it to secret_number
    while True:
        player_guess = int(input("Guess a number between 1 and 10: "))
        if player_guess == secret_number:
            print("you got it! My number was {}.".format(secret_number))
            break
        else:
            print("guess again")
game()

You can also add a secret_number parameter to the game function to allow you to pass it a random number as you call the function, like this:

import random
# generate a random number between 1 and 10
def choose_secret_number():
    return random.randint(1,10) # Return the random number

# get a number guess from the player
def game(secret_number): # Define secret_number as parameter
    while True:
        player_guess = int(input("Guess a number between 1 and 10: "))
        if player_guess == secret_number:
            print("you got it! My number was {}.".format(secret_number))
            break
        else:
            print("guess again")

game(choose_secret_number())  # Generate random number and pass it in to the game function

That is a more complex example as it makes use of parameters, essentially variables that are assigned a value when the function is called, and arguments which are values that are passed to the function.

Variable scopes and parameters/arguments is something you will learn more about later on so you don't need to worry too much if these examples are not very clear to you right now. I just wanted to show some examples of how an issue like this could be dealt with.

Edit: Changed my wording a bit.

Edit2: Accidentally left a line of code in the second example that did not belong.

Fantastic. Great to know it's just not something I'd seen thus far after banging my head against it for so long.

Super clear explanation, thanks!