1

I am new to coding and am working on a simple math project. I have the following code:

#!/usr/bin/env python3
import sys; print(sys.version)
import random

##Creates values to use to make random equation.

x = random.randint(1,11)
y = random.randint(1,11)
if x > y:
    total = random.randint(x, 20)
else:
    total = random.randint(y, 20)

##Creates actual values for A,B,C, and D in equation A+B=C+D

a = x
b = total - a
c = y
d = total - y

##Prints option choices and asks for user input

def start_game_message():
    print ("Please fill in the blanks to make the following equation true:")
    print ("__+__=__+__")
    print ("The option choices are:" + str(a) + ", " + str(b) + ", "  + str(c) + ", " + str(d))
def ask_for_input():
    blank1 = input("What is the value of the first blank?")
    blank2 = input("What is the value of the second blank?")
    blank3 = input("What is the value of the third blank?")
    blank4 = input("What is the value of the fourth blank?")
start_game_message()
##Check if user input is correct
def check_answer():
    ask_for_input()
    print (blank1)
    if int(blank1)+ int(blank2) == int(blank3) + int(blank4):
        print ("That is correct!")
    else:
        print ("That is incorrect. Please try again.")
        ask_for_input()
check_answer()

When running this I get the following error:

Traceback (most recent call last):
  File "C:/Users/duncs/PycharmProjects/moms_app/main", line 42, in <module>
    check_answer()
  File "C:/Users/duncs/PycharmProjects/moms_app/main", line 36, in check_answer
    print (blank1)
NameError: name 'blank1' is not defined

Am I doing something wrong? I input values for each blank that should be stored. If I put print(blank1) within the ask_for_inputs function, it prints just fine. But when I call the function later on inside the check_answers function it results in the error. Can i not call a function in another function? Please help! Thank you.

aghast
  • 14,785
  • 3
  • 24
  • 56
Duncan
  • 13
  • 3

4 Answers4

1

You've got a problem with your scope — see this SO answer for more.

The short of it is that the check_answer function can't "see" the blank1 variable. blank1 was only ever referenced inside ask_for_input before you define check_answer, and in Python (and most modern languages) this doesn't work. Functions are selfish and like to keep everything inside them for themselves; you have to work with them to get them to share with other functions.

There are a few solutions:

  1. Make blank1 global (however you should not do this — see here)
  2. Define check_answer inside ask_for_input (I don't recommend this)
  3. Pass blank1 as a parameter and return the results of the input calls in ask_for_input back to the caller so you can thread the user input out of ask_for_input and into check_answer

I recommend going with 3, personally. I can elaborate with more concrete examples if needed.

Community
  • 1
  • 1
Pierce Darragh
  • 2,072
  • 2
  • 16
  • 29
1

I think the best way to approach this would be to fix your ask_for_input():

def ask_for_input(which):
    return input("What is the value of the %s blank?" % which)
start_game_message()
##Check if user input is correct
def check_answer():
    inputs = []
    for blank in ['first', 'second', 'third', 'fourth']:
        inputs.append(ask_for_input(blank))

    if int(inputs[0])+ int(inputs[1]) == int(inputs[2]) + int(inputs[3]):
        print ("That is correct!")
    else:
        print ("That is incorrect. Please try again.")
        ask_for_input()
check_answer()

This avoids your scope issue by passing the result back via return. It also reduces code repetition and takes advantage of a list to store the 4 inputs.

As to why your code doesn't work, it's because if you examined the stack you'd see:

global
    check_answer
        ask_for_input
        -blank1
        -blank2
        -blank3
        -blank4

When ask_for_input returns, it's stack frame is lost:

global
    check_answer

So you have to figure out how to get those results out, either by assigning to variables which are in a broader scope (the suggestions for global) or via return.

TemporalWolf
  • 7,727
  • 1
  • 30
  • 50
  • You've provided a complete solution without really explaining to OP why your solution is better than the original submission. Also: "if you exampled the stack" — what exactly does this mean? By which I mean: How is OP supposed to understand this string of words together when they're so new to coding? – Pierce Darragh Mar 24 '17 at 06:09
  • @PierceDarragh I have no problem clarifying things if OP has questions, and I do expect some ability to look up solutions. You list three options, two of which are admittedly bad, then say you can elaborate if needed. I just cut straight to the chase. I also see your explanation as complementary and no reason to repeat that, although I would disagree with personifying functions. And good eye: I fixed that typo... I think I may have combined examine with sampled... exsampled xD. – TemporalWolf Mar 24 '17 at 06:41
  • Fair enough; OP clearly liked your solution better anyway so it's a moot point there, haha. :) I don't think inner function definitions are "bad" per se... but certainly not the correct choice for this problem (which is why I said I would suggest the third option, though I guess I wasn't explicit enough with that!). Cheers! – Pierce Darragh Mar 24 '17 at 06:45
  • Thank you so much. I hadn't learned about global variables vs local variables. Also didn't think of a creative way to take the input like you did. Thanks alot. – Duncan Mar 24 '17 at 07:31
  • @Duncan Anytime you find yourself repeating the same thing over and over you're probably doing more work than you need to. – TemporalWolf Mar 24 '17 at 07:40
0

the scope of blank1 variable is limited to the ask_for_input() function. you need to declare all the blank variables outside the function definition globally.

Add after the following line

d = total - y
blank1=''
blank2=''
blank3=''
blank4=''
blank5=''
Akshay Apte
  • 1,539
  • 9
  • 24
0

The scope of blank1, as well as the other blank variables, are only local variables. You have to make them global variables.

*edit: looks like I'm a bit late on the response. The other answers are great solutions.

Synnennennen
  • 1
  • 1
  • 2