0

I am learning Python and am making a Q&A script. I made one function for the questions. That went rather well. Now I am wanting an average function. I want to avoid using globals if at all possible. I know that my variables reset at the top... can someone please give me some pointers? I know C/PHP/BASIC and want to grasp this langauge. Below is my question function.

    def q(question, a, b, c, c_answer):
        total,tally=0,0
        print "",question
        print "   a.",str(a)
        print "   b.",str(b)
        print "   c.",str(c)
        u_answer = raw_input()
        if c_answer == "a" and u_answer == "a":
            print "Correct, the answer is A!"
            tally+=1
        elif c_answer == "b" and u_answer == "b":
            print "Correct, the answer is B!"
            tally+=1
        elif c_answer == "c" and u_answer == "c":
            print "Correct, the answer is C!"
            tally+=1
        else:
           print "I am sorry, but the correct answer is",c_answer
        print "\..n"
        total+=1
2
  • Which version r u using? Commented Mar 5, 2012 at 19:11
  • I mean something that takes an average. Its more of a statement: (x/y)*100 Commented Mar 5, 2012 at 19:15

2 Answers 2

4

Remove total from the q function. Instead, return 1 if the question is answered correctly, 0 otherwise:

def q(question, a, b, c, c_answer):
    ...
    return tally

num_correct = 0
for question in questions:
    num_correct += q(...)

average = float(num_correct) / len(questions)

If you don't want to use globals, simply organize your code in functions or class methods:

def ask_questions(questions):
    num_correct = 0
    for question in questions:
        num_correct += q(...)
    return num_correct

def report_average(num_correct, num_questions):
    average = float(num_correct) / num_questions
    print(average)

num_correct = ask_questions(questions)
report_average(num_correct, len(questions))

I think the basic idea is to use return to pass on the value(s) you need to the next function. If there are many pieces of data to keep track of, you could instead use class methods. By using a class, you can store values as instance attributes instead of using return:

class Exam(object):
    def __init__(self, questions):
        self.num_correct = 0
        self.questions = ...

    def q(self, question, a, b, c, c_answer):
        ...
        if correct:
            self.num_correct += 1

    def ask_questions(self):
        for question in self.questions:
            self.q(question)

    def report_average(self):
        average = float(self.num_correct) / len(self.questions)
        print(average)
Sign up to request clarification or add additional context in comments.

3 Comments

I know that the "..." means to insert my code, but I am confused as to where I print my question and check my answers from a pool of A,B, or C :-(
i find your code nice, but the class system is alien to me. is it the same as c++
I think a very good explain of Python's class system (including a bit of comparison to C++) can be found here.
0

Since you're just learning Python, I reformatted your code to be more pythonic.

def q(question, a, b, c, c_answer):
    total, tally = 0, 0
    print "", question
    print "   a. %s" % a
    print "   b. %s" % b
    print "   c. %s" % c
    u_answer = raw_input("your answer? ").strip()
    if c_answer == u_answer:
        print "Correct, the answer is %s!" % u_answer
        tally += 1
    else:
        print "I am sorry, but the correct answer is %s" % c_answer
    print "\n"
    total += 1

To actually answer your question:

There a couple ways to keep track of the total number of questions and correct answers without using global-level variables (actually module-level, but that's a different topic ;).

One is to pass in the current totals, have q recalculate based on the current question, and then pass them back out:

def q(question, a, b, c, c_answer, total, tally):
    print "", question
    print "   a. %s" % a
    print "   b. %s" % b
    print "   c. %s" % c
    u_answer = raw_input("your answer? ").strip()
    if c_answer == u_answer:
        print "Correct, the answer is %s!" % u_answer
        tally += 1
    else:
        print "I am sorry, but the correct answer is %s" % c_answer
    print "\n"
    total += 1
    return total, tally

Then in your main program you can say:

question_pool = (
    ('What is 2 + 2?', 2, 3, 4, 'c'),
    ('What is blue mixed with yellow?', 'green', 'orange', 'pink', 'a'),
    ('How far does light travel in one nanosecond?', '10 mm', '20 cm', '30 m', 'b'),
    )

total, tally = 0, 0
for packet in question_pool:
    question, a, b, c, answer = packet
    total, tally = q(question, a, b, c, answer, total, tally)

print "you answered %d correctly, for a score of %2.0f%%" % (tally, 100.0 * tally / total)

However, it would be better for q to just deal with questions, and not worry about keeping track of how many questions have been answered and how many questions have been asked.

So instead of accepting total and tally, recalculating, and returning total and tally, q will now just return 0 if the answer was wrong, 1 if it was correct:

def q(question, a, b, c, c_answer):
    print "", question
    print "   a. %s" % a
    print "   b. %s" % b
    print "   c. %s" % c
    u_answer = raw_input("your answer? ").strip()
    if c_answer == u_answer:
        print "Correct, the answer is %s!\n" % u_answer
        return 1
    print "I am sorry, but the correct answer is %s" % c_answer
    return 0

and the rest of the code looks like:

question_pool = (
    ('What is 2 + 2?', 2, 3, 4, 'c'),
    ('What is blue mixed with yellow?', 'green', 'orange', 'pink', 'a'),
    ('How far does light travel in one nanosecond?', '10 mm', '20 cm', '30 m', 'b'),
    )

total, tally = 0, 0
for packet in question_pool:
    question, a, b, c, answer = packet
    tally += q(question, a, b, c, answer)
    total += 1

print "you answered %d correctly, for a score of %.0f%%" % (tally, 100.0 * tally / total)

1 Comment

Doing this in C++ or BASIC didn't trouble me... Python is just that way I guess!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.