2 questions about my Python homework (no wars, please)

Discussion in 'Scripting & Programming' started by tripwire45, Mar 14, 2008.

  1. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    Actually, I did rather well with this one. I was supposed to create a menu that included the options to list the menu, list the questions and answers for a test, have the user take a test and get feedback about each answer, and to be able to quit the program.

    The program does all this (I did borrow from your prior example, Mathematix...hope you don't mind). I do have two problems though, and I feel distinctly stupid since I know they have simple answers.

    1. I keep getting this message when I first run the program. The program runs fine, but I don't know how to debug the thing to correct the issue:
    2. When you run option 2, you are asked if you want to see the questions and answers to the test. If you answer "yes", the information is displayed. If you answer "no", you are directed to the option that will let you take the test. If you input any other text, you get an error message saying (whatever the text happens to be) isn't defined. I've tried using else and elif to include a line that will handle any other input and print a response saying "Please answer yes or no", but nothing works. I know there is a simple answer, but I can't recall it and unfortunately, I'm not even sure how to search for the answer. I put a comment in the code (below) marking the spot.

    Thanks in advance for your help. Other than these two minor issues, I really did puzzle through this on my own (old dog learning new tricks?).

    Code:
    import test
    
    valid_options = ['1','2','3','4']
    
    def print_options():
        print "Main menu"
        print "======================"
        print " '1'  Print Options"
        print " '2'  Get Questions and Answers"
        print " '3'  Start the test"
        print " '4'  Quit"
        print "======================"
    
    yes = 3
    no = 4
    def q_a():
            
        response = input("Do you want to know the questions and answers? Answer 'yes' or 'no' ")
        positive_answer = yes
        negative_answer = no
        if response == positive_answer:
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        if response == negative_answer:
             print "Then test your knowledge and take the test by selecting option 3"
    #What do I put here so that if any other answer is entered, I can print something like:
    #"Please, answer yes or no"?
    
    true = 1
    false = 0
       # First get the test questions
       # Later this will be modified to use file io.
    def get_questions():
           # notice how the data is stored as a list of lists
           return [["What color is the daytime sky on a clear day?","blue"],\
                    ["What is the answer to life, the universe and everything?","42"],\
                    ["What is a three letter word for mouse trap?","cat"],\
    		["What noise does a truly advanced machine make?","ping"]]
       # This will test a single question
       # it takes a single question in
       # it returns true if the user typed the correct answer, otherwise false
    def check_question(question_and_answer):
           #extract the question and the answer from the list
           question = question_and_answer[0]
           answer = question_and_answer[1]
           # give the question to the user
           given_answer = raw_input(question)
           # compare the user’s answer to the testers answer
           if answer == given_answer:
                print "Correct"
                return true
           else:
                print "Incorrect, correct was:",answer
                return false
    
    # This will run through all the questions
    def run_test(questions):
        if len(questions) == 0:
            print "No questions were given."
            # the return exits the function
            return
        index = 0
        right = 0
        while index < len(questions):
            #Check the question
            if check_question(questions[index]):
                right = right + 1
            #go to the next question
            index = index + 1
        #notice the order of the computation, first multiply, then divide
        print "You got ",right*100/len(questions),"% right out of",len(questions)
    #now lets run the questions
    
    
    def run():
        
        global valid_options
        
        option = ""
    
        while True:
            print_options()
            
            if option.lower() not in valid_options:
                option = raw_input("Please choose an option:")
    
            if option.lower() == "1":
                option = ""
                continue
    
            if option.lower() == "2":
    	    q_a()
                option = ""
    	    continue
    
    	if option.lower() == "3":
    	    run_test(get_questions())
    	    option = ""
    	    continue
    
            if option.lower() == "4":
                break
    
    if __name__ == '__main__':
        run()
    
     
    Certifications: A+ and Network+
  2. hbroomhall

    hbroomhall Petabyte Poster Gold Member

    6,624
    117
    224
    Pure guesswork on the non-ascii character point:

    Pull the code into a 'text editor' (i.e. not one where Microsoft is trying to be clever). I suspect the problem is the apostrophe in the line about "users' answer". You need to use ' not ´.

    Harry. (Not a python expert)
     
    Certifications: ECDL A+ Network+ i-Net+
    WIP: Server+
  3. hbroomhall

    hbroomhall Petabyte Poster Gold Member

    6,624
    117
    224
    Remember that I'm not a python programmer but this
    Code:
        positive_answer = yes
        negative_answer = no
    seems wrong to me. Surely this should be
    Code:
        positive_answer = 'yes'
        negative_answer = 'no'
    i.e. the test strings should be quoted?

    Harry.
     
    Certifications: ECDL A+ Network+ i-Net+
    WIP: Server+
  4. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    Wow! Yes, this looks much better than you other attempt.


    No problem. All I did was rearrange your code, so use it as you see fit. :)

    You may have noticed that Python has gone through several minor revisions in order to get to its current (2.5.x). When programming languages are revised certain features are removed or succeeded by improved implementations. The new implementation causes its predecessor to be 'deprecated', which means that the old implementation will no longer be featured in later versions of the language. I suspect that you are learning from a version of Python prior to 2.5 but are coding in a 2.5 environment.


    You've set yourself up for a classic Python trap as well as a fairly common programming mistake. Let's look at a code snippet:

    Code:
    yes = 3
    no = 4
    def q_a():
        ...
        positive_answer = yes
        negative_answer = no
    
    You have define 'yes' and 'no' in the global space but are not referring to them in your function q_a(). This is an example of undefined behaviour (the consequences of running such code cannot be reasonably predicted). You really should have had something like:

    Code:
    yes = 3
    no = 4
    def q_a():
        ...
    
        global yes
        global no
    
        positive_answer = yes
        negative_answer = no
    
    By having 'global yes' and 'global no' you are telling Python to refer to the global definitions of 'yes' and 'no'. This is still not a good solution, leading me to the point where I show the programming trap that you've set up for yourself.

    When you ask the question

    Code:
        response = input("Do you want to know the questions and answers? Answer 'yes' or 'no' ")
    
    You are asking the user to choose between one of two states: 'yes' and 'no'. This scenario fits the boolean states 'true' and 'false'. In your code you are specifically trying to get 'yes' and 'no' which isn't necessary and are undefined, and means that you are using two variables where only one is required, and also unnecessarily redefining 'true' and 'false'. Here is how I would rework the code:

    Code:
    def q_a():
        ...
    
         response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
    
         if response.lower() == 'y':
            # Do necessary stuff for 'y' response.
         elif response.lower() == 'n':
            # Do necessary stuff for 'n' response.
         else:
            # Unrecognised response handling code. Go and ask question again.
    
    We now have a more flexible system and got rid of two variable declarations.

    On an unrelated side note to the problem above I've also notice that you've redefined true and false when Python already has a built-in boolean type that takes values 'True' and 'False'.
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  5. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    Here's my responses so far:

    Harry...when I made the suggested changes as follows:
    Code:
        positive_answer = 'yes'
                  negative_answer = 'no'
    I get an error message. When I remove the single quotes, the program works again.

    Thanks for the non-ASCII character help Harry and Math. I can usually spot those (a lot of copying and pasting is going on here), but I missed this one.

    Math, I made the changes as follows:
    Code:
    def q_a():
       
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
    
    
        if response.lower() == 'y':
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        elif response.lower() == 'n':
             print "Then test your knowledge and take the test by selecting option 3"
    
        else:
            # Unrecognised response handling code. Go and ask question again.
    Unfortunately, I must have broken something in the process because when I try to run the program now, here's what I get:
    Code:
    jmpyles@lamp:~$ cd python
    jmpyles@lamp:~/python$ python 8-4exercise.py
      File "8-4exercise.py", line 31
        true = 1
        ^
    IndentationError: expected an indented block
    jmpyles@lamp:~/python$
    
    As far as the redefining of 'true' and 'false' go, that part is copied from an original sample program in the lesson I'm using that I'm supposed to use as the basis for this assignment. I suspect though, that this is what may be causing the error I'm now getting when I modify my program according to your suggestion.

    When I change everything to the following, the program works again:
    Code:
    yes = 3
    no = 4
    def q_a():
    
        global yes
        global no
    
        positive_answer = yes
        negative_answer = no
    
        response = input("Do you want to know the questions and answers? Answer 'yes' or 'no' ")
        if response == positive_answer:
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        if response == negative_answer:
             print "Then choose option 3 and take the test"
    
    true = 1
    false = 0
       # First get the test questions
       # Later this will be modified to use file io.
    Don't give up on me, yet. I'm still trying to figure this out. I appreciate all of the time you're spending here and particularly your patience and your expertise. :)
     
    Certifications: A+ and Network+
  6. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    Maybe the reason why you are getting the indentation error is because of

    Code:
        else:
            # Unrecognised response handling code. Go and ask question again.
    
    ?

    You have followed the 'else' with nothing as far as the parser is concerned, and I suspect this is causing the error. Replace the comment with 'pass' or remove the 'else' completely. :)
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  7. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    My bad. Thanks. :oops:
     
    Certifications: A+ and Network+
  8. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    A few months ago I stared at one of those sorts of errors for the best part of 15 minutes before I realised! :tomato
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  9. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    This is how this section of the code seems like it should be reworked based on what you said:
    Code:
    def q_a():
    
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
        if response.lower() == 'y':
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        elif response.lower() == 'n':
             print "Then choose option 3 and take the test."
        else:
             print "Please answer 'y' or 'n'. "
    It seems like
    Code:
    else:
                   print "Please answer 'y' or 'n'. "
    should just work. Unfortunately, that's not the case:
    Here's what happens when I try to answer the question with "y" (without the quotation marks):
    Code:
    Please choose an option:2
    Do you want to know the questions and answers? Answer 'y' or 'n' y
    Traceback (most recent call last):
      File "8-4exercise.py", line 105, in ?
        run()
      File "8-4exercise.py", line 92, in run
        q_a()
      File "8-4exercise.py", line 17, in q_a
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
      File "<string>", line 0, in ?
    NameError: name 'y' is not defined
    It seems like you're saying that 'y' and 'n' don't need to be defined based on:
    What am I missing?
     
    Certifications: A+ and Network+
  10. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    Looks like I make a little mistake earlier as well, sorry... my bad. In Python there are two ways of delimiting strings, that is using both single quotes and double quotes. Like many other programming laguages, when special characters are used within a string they need to be 'escaped', so

    Code:
    else:
                   print "Please answer 'y' or 'n'. "
    
    becomes

    Code:
    else:
                   print "Please answer \'y\' or \'n\'. "
    
    Where the backslash becomes the 'escape character' telling the parser that the single quote has no special meaning within the string and should be treated as a literal character.

    That should fix your problem. :)
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  11. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    Uh...I'm obviously not understanding what you're suggesting here. Here's what I've got based on your latest post:
    Code:
    def q_a():
    
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
        if response.lower() == 'y':
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        elif response.lower() == 'n':
             print "Then choose option 3 and take the test."
        else:
             print "Choose either \'y\' or \'n\' "
    Here's what happens:
    Code:
    Main menu
    ======================
     '1'  Print Options
     '2'  Get Questions and Answers
     '3'  Start the test
     '4'  Quit
    ======================
    Please choose an option:2
    Do you want to know the questions and answers? Answer 'y' or 'n' y
    Traceback (most recent call last):
      File "8-4exercise.py", line 105, in ?
        run()
      File "8-4exercise.py", line 92, in run
        q_a()
      File "8-4exercise.py", line 17, in q_a
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
      File "<string>", line 0, in ?
    NameError: name 'y' is not defined
    jmpyles@lamp:~/python$
    I tried using the same delimiters in the statement "Do you want to know the questions and answers? \'y\' or \'n\' " but it didn't help. Sorry to be so "pesky", but I feel I must be missing something basic. Even though I *think* I'm applying your suggestions as stated, I must be missing a step. Just to review, I'm posting the current incarnation of the entire program again, just in case something was introduced that's messing up the works:
    Code:
    import test
    
    valid_options = ['1','2','3','4']
    
    def print_options():
        print "Main menu"
        print "======================"
        print " '1'  Print Options"
        print " '2'  Get Questions and Answers"
        print " '3'  Start the test"
        print " '4'  Quit"
        print "======================"
    
    
    def q_a():
    
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
        if response.lower() == 'y':
             print "What color is the daytime sky on a clear day? Answer: blue"
             print "What is the answer to life, the universe and everything? Answer: 42"
             print "What is a three letter word for mouse trap? Answer: cat"
             print "What noise does a truly advanced machine make? Answer: ping"
    
        elif response.lower() == 'n':
             print "Then choose option 3 and take the test."
        else:
             print "Choose either \'y\' or \'n\' "
    
    true = 1
    false = 0
       # First get the test questions
       # Later this will be modified to use file io.
    def get_questions():
           # notice how the data is stored as a list of lists
           return [["What color is the daytime sky on a clear day?","blue"],\
                    ["What is the answer to life, the universe and everything?","42"],\
                    ["What is a three letter word for mouse trap?","cat"],\
    		["What noise does a truly advanced machine make?","ping"]]
       # This will test a single question
       # it takes a single question in
       # it returns true if the user typed the correct answer, otherwise false
    def check_question(question_and_answer):
           #extract the question and the answer from the list
           question = question_and_answer[0]
           answer = question_and_answer[1]
           # give the question to the user
           given_answer = raw_input(question)
           # compare the user's answer to the testers answer
           if answer == given_answer:
                print "Correct"
                return true
           else:
                print "Incorrect, correct was:",answer
                return false
    
    # This will run through all the questions
    def run_test(questions):
        if len(questions) == 0:
            print "No questions were given."
            # the return exits the function
            return
        index = 0
        right = 0
        while index < len(questions):
            #Check the question
            if check_question(questions[index]):
                right = right + 1
            #go to the next question
            index = index + 1
        #notice the order of the computation, first multiply, then divide
        print "You got ",right*100/len(questions),"% right out of",len(questions)
    #now lets run the questions
    
    
    def run():
        
        global valid_options
        
        option = ""
    
        while True:
            print_options()
            
            if option.lower() not in valid_options:
                option = raw_input("Please choose an option:")
    
            if option.lower() == "1":
                option = ""
                continue
    
            if option.lower() == "2":
    	    q_a()
                option = ""
    	    continue
    
    	if option.lower() == "3":
    	    run_test(get_questions())
    	    option = ""
    	    continue
    
            if option.lower() == "4":
                break
    
    if __name__ == '__main__':
        run()
    
     
    Certifications: A+ and Network+
  12. hbroomhall

    hbroomhall Petabyte Poster Gold Member

    6,624
    117
    224
    This thread has prompted me to download the Windows version of Python and look at it! (I blame you! :p )

    I have now half an idea as to what is going wrong, and why my original suggestion was wrong.

    The problem is that I'm the wrong side of an excellent bottle of wine, so I'll be continuing in the morning....

    I'll leave you with the point that the input function does some surprising things (both to the newbie and others). Basicaly it seems to get the input and *then interprets it*.

    So when you type "yes" this is returned and then interpreted, rather than being used as a string. The result of this interpretation is to give whatever the variable 'yes' contains.
    This may not be what you want.

    Harry.
     
    Certifications: ECDL A+ Network+ i-Net+
    WIP: Server+
  13. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    Whenever you wish for the user to enter an answer to a question you need to ensure that Python understands the input as a string. So with

    Code:
        response = input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
        if response.lower() == 'y':
    
    the user is forced to specifically 'quote' their answer, eg - valid answers would be

    Code:
    "y"
    
    or

    Code:
    'y'
    
    But changing the above to use raw_input() instead of input() doesn't for the user to quote their resposes. So change the code to...

    Code:
        response = raw_input("Do you want to know the questions and answers? Answer 'y' or 'n' ")
        if response.lower() == 'y':
    
    That will work!

    About the boolean bit I spoke about earlier. ignore it as you've chosen to structure you program differently. :biggrin
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  14. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    ROFL! :alc

    Enjoy! :biggrin
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.
  15. tripwire45
    Honorary Member

    tripwire45 Zettabyte Poster

    13,493
    180
    287
    Bingo! That did it. Thanks. :biggrin
     
    Certifications: A+ and Network+
  16. Mathematix

    Mathematix Megabyte Poster

    969
    35
    74
    No probs, mate! :)
     
    Certifications: BSc(Hons) Comp Sci, BCS Award of Merit
    WIP: Not doing certs. Computer geek.

Share This Page

Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.