Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Refactor code to remove global variable

I am currently using a global variable in my code called correct. Considering globals are frowned upon, is there a better way to set up my code to "protect" the global variable?

from random import randint
from random import choice

lower  = int(raw_input("Enter a lower integer constraint: "))
higher = int(raw_input("Enter a higher integer constraint: "))

correct = 0


def gen_randoms(lower, higher):
    integers = list()
    for x in xrange(4):
        rand_int = randint(lower, higher)
        integers.append(rand_int)
    return integers


def gen_equation(integers):
    nums = map(str, integers)
    operators = ['*', '+', '-']
    equation = 'num op num op num op num'
    while 'op' in equation:
        equation = equation.replace('op', choice(operators), 1)
    while 'num' in equation:
        equation = equation.replace('num', choice(nums), 1)
    print equation
    return equation


def evaluate(equation):
    answer = eval(equation)
    print answer
    return answer


def compare_answers(gen_answer, game):
    global correct
    user_answer = int(raw_input("What is the answer? "))
    if user_answer == gen_answer:
        correct += 1
        print 'Correct!'
        print 'Current streak: %s' % str(correct)
        game()
    else:
        print 'Incorrect!'
        correct = 0
        game()


def game():
    nums = gen_randoms(lower, higher)
    this_equation = gen_equation(nums)
    gen_answer = evaluate(this_equation)
    compare_answers(gen_answer, game)


game()
like image 416
Evan Emolo Avatar asked Oct 03 '22 03:10

Evan Emolo


1 Answers

I'd probably do it something like this:

#!/usr/bin/python

"""Equation solving game."""

from random import randint
from random import choice


def gen_randoms(lower, higher):

    """Generates four random numbers between provided bounds."""

    integers = [randint(lower, higher) for x in range(4)]
    return integers


def gen_equation(integers):

    """Generates a random equation from four provided integers."""

    nums = [str(i) for i in integers]
    operators = ['*', '+', '-']
    equation = 'num op num op num op num'
    while 'op' in equation:
        equation = equation.replace('op', choice(operators), 1)
    while 'num' in equation:
        equation = equation.replace('num', choice(nums), 1)
    return equation


def evaluate(equation):

    """Evaluates an equation."""

    return eval(equation)


def main():

    """Main game function."""

    lower = int(raw_input("Enter a lower integer constraint: "))
    higher = int(raw_input("Enter a higher integer constraint: "))
    nums = gen_randoms(lower, higher)
    streak = 0

    while True:
        this_equation = gen_equation(nums)
        print this_equation

        user_answer = raw_input("What is the answer? ('Q' to quit) ")

        if user_answer.lower()[0] == 'q':
            break

        gen_answer = evaluate(this_equation)
        print 'The answer was: %d' % gen_answer

        if gen_answer == int(user_answer):
            streak += 1
            print 'Correct!'
            print 'Current streak: %d' % streak
        else:
            streak = 0
            print 'Incorrect!'


if __name__ == "__main__":
    main()

A few comments:

  • Each function should generally only do one thing, so if a function evaluates an equation, it's usually better to not have it print the equation, too.
  • Figuring out where the variables ought to go becomes a lot easier when you do this, since you don't need to pass them around so much as you have to when each function does several different things.
  • The main game logic here is sufficiently straightforward that you don't really need to break it out of your main game() function (or main() function, in my example) so much, it doesn't overcomplicate things to leave it in there. If you wanted to do some more error checking (e.g. seeing if the user entered an invalid number, and you want to go back and ask for more input if so) then you might want to break it out some more.
like image 102
Crowman Avatar answered Oct 07 '22 16:10

Crowman