CowardlyFrench
CowardlyFrench

Reputation: 435

Why does my simple program never exit my while loop?

It's a simple number guessing game, and the code is as follows:

from random import randint

number = randint(0,20)
playerGuess = '0'
def guess():
    playerGuess = input("Guess a number:  ")

    if int(playerGuess) == number:
        print("Correct!")

    elif int(playerGuess) > number:
        print("Lower!")

    elif int(playerGuess) < number:
        print("Higher!")

    else:
        print("Please input a whole number.")

while int(playerGuess) != number:
    guess()

print("------------------------------------")
print("Good job!") 

I do not understand why the code does not break out of the while loop as expected.

Upvotes: 0

Views: 151

Answers (3)

MackM
MackM

Reputation: 3022

Variables only exist in their 'namespace', which is the part of the code different variables are recognized. A new namespace is made for each function you write. This is helpful because as your projects grow, you may want to reuse common variables names for several different things.

In your code, there are two different variables named playerGuess. One in the first namespace, and one in the namespace that you made for your function guess(). If we make the code like this:

while int(playerGuess) != number:
    print(playerGuess, number)           # The added line
    guess()

It becomes more clear. This is a game I played with the added line:

0 14
Guess a number:
>>> 10
0 14     # playerGuess is still 0, not 10
Higher!
Guess a number:  
>>> 14
0 14     # I've been told I won because that happens in the guess() function
Correct!
Guess a number:  # But the while: loop doesn't know I've won
. . .

The namespace in your script outside of any functions, like where number = randint(0,20) is, is the 'global' namespace, which means values can be pulled from here from any other namespace. This is why number can be used by the guess() function- guess() checks to see if there is a variable number defined in its namespace, sees there is not, and then checks the global namespace. It is possible to change the global namespace from other parts of the code, but this is considered bad practice because it can be not obvious where these changes come from. If you wanted to take this approach though, you could alter your code like this:

from random import randint

number = randint(0,20)
playerGuess = '0'
def guess():
    global playerGuess                  # The added line
    playerGuess = input("Guess a number:  ")
. . .

And now it works because guess() has been given explicit permission to alter the global namespace. An alternative is to pass only the value we care about back and forth between the namespaces.

from random import randint
number = randint(0,20)
playerGuess = '0'
def guess():
    playerGuess = input("Guess a number:  ")

    if int(playerGuess) == number:
        print("Correct!")

    elif int(playerGuess) > number:
        print("Lower!")

    elif int(playerGuess) < number:
        print("Higher!")

    else:
        print("Please input a whole number.")

    return playerGuess                     # Added line

while int(playerGuess) != number:
    print(playerGuess, number)
    playerGuess = guess() # Added line, update the playerGuess in this namespace

This is considered better because now it is obvious exactly where and what alters the variable playerGuess.

Upvotes: 0

pancakes
pancakes

Reputation: 712

Because playerGuess in guess() function is not the same variable as playerGuess of the top of file. Use global playerGuess in guess() function.

from random import randint

number = randint(0,20)
playerGuess = '0'
def guess():
    global playerGuess
    ...

Tips&tricks: Global variables are bad, try to rewrite your code without globals.

Upvotes: 1

Dair
Dair

Reputation: 16240

guess doesn't change the global value of playerGuess = '0' To do that you need to specify with the global, although there are better ways to refactor your code:

from random import randint

number = randint(0,20)
playerGuess = '0'
def guess():
    global playerGuess #Emphasis on this line.
    playerGuess = input("Guess a number:  ")

    if int(playerGuess) == number:
        print("Correct!")

    elif int(playerGuess) > number:
        print("Lower!")

    elif int(playerGuess) < number:
        print("Higher!")

    else:
        print("Please input a whole number.")

while int(playerGuess) != number:
    guess()

print("------------------------------------")
print("Good job!") 

Upvotes: 1

Related Questions