2013-08-25 3 views
5

В настоящее время я использую глобальную переменную в моем коде под названием correct. Учитывая, что глобальные переменные не одобряются, есть ли лучший способ настроить мой код для «защиты» глобальной переменной?Python: Код refactor для удаления глобальной переменной

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() 
+0

Имейте в виду вход и возврат от compare_answers()? – Jiminion

+0

Самый простой способ - вставить 'compare_answers()' в 'game()' и переместить переменную 'correct' в' game() '. – Nayuki

+0

Кроме того, тот факт, что вы используете хвостовую рекурсию в 'game()' и 'compare_answers()', означает, что вы в конечном итоге закончите пространство стека. – Nayuki

ответ

3

я бы, вероятно, сделать что-то вроде этого:

#!/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() 

Несколько комментариев:

  • Каждая функция должна вообще делать только одну вещь, так что если функция вычисляет уравнение, это обычно лучше не печатать это уравнение.
  • Выяснить, где переменные должны идти, становится намного легче, когда вы это делаете, поскольку вам не нужно передавать их так, как вам нужно, когда каждая функция выполняет несколько разных действий.
  • Основная логика игры здесь достаточно проста, что вам действительно не нужно вырывать ее из вашей основной функции game() (или main(), в моем примере) так много, это не слишком усложняет ситуацию, чтобы оставить ее там , Если вы хотите сделать еще некоторую проверку ошибок (например, если пользователь указал неверный номер, и вы хотите вернуться назад и попросить больше ввода, если это так), вы можете захотеть его разбить.
1

что-то вроде этого:

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

Добавить это:

def game(): 
    correct = 0 
    while True: 
     nums = gen_randoms(lower, higher) 
     this_equation = gen_equation(nums) 
     gen_answer = evaluate(this_equation) 
     user_answer = int(raw_input("What is the answer? ")) 
     if user_answer == gen_answer: 
      correct += 1 
      print 'Correct!' 
      print 'Current streak: %s' % str(correct) 
     else: 
      print 'Incorrect!' 
      correct = 0 

Затем удалите эти куски старого кода: game(), compare_answers(), и глобальная переменная correct.

0
  1. удалить global correct из compare_answers
  2. установить game взять в именованного аргумента correct со значением по умолчанию 0. def game(correct =0)
  3. набор compare_answers взять третий аргумент correct
  4. при вызове game из compare_answers прохода в correct

т.е.

def compare_answers(gen_answer, game, 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(correct) 
    else: 
     print 'Incorrect!' 
     correct = 0 
     game(correct) 


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


game() 
0

я в конечном итоге принимает @ предложение JoelCornett и создании класс:

from random import randint 
from random import choice 

class Math_Problem_Generator(object): 

    def __init__(self): 
     self.lower = int(raw_input("Enter a lower integer constraint: ")) 
     self.higher = int(raw_input("Enter a higher integer constraint: ")) 
     self.correct = 0 
     self.game(self.correct) 


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


    def gen_equation(self, 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(self, equation): 
     answer = eval(equation) 
     print answer 
     return answer 


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


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


Math_Problem_Generator() 
+2

FYI, в то время как это работает, это не очень хороший ООП, и это все еще просто процедурная программа, слегка обернутая синтаксисом ООП. Например, три из ваших пяти методов (исключая '__init __()') не имеют доступа к данным экземпляра или не вызовут какие-либо методы экземпляра, что говорит о том, что они не относятся к классу. Он удаляет проблему глобальных переменных, но заканчивается заменой одной плохой практики для другой. –

+0

Разве это не так уж плохо, если пакет '__init __()' call' self.game() '? Вы должны отделить 'game()' или 'run()' out от '__init() __'. Вы всегда можете объявить и запустить его (анонимно) как однострочный с помощью 'Math_Problem_Generator(). Run()' – smci

0

Соберите результаты в вызывающем абоненте, а затем распечатайте счет. Эта версия избавляется от ваших других глобальных переменных, lower и higher.

def compare_answers(gen_answer): 
    user_answer = int(raw_input("What is the answer? ")) 
    return user_anser == gen_answer 

def game(): 

    correct = 0 
    play_again = 'Y' 

    while play_again.lower() == 'y': 
     lower = int(raw_input("Enter a lower integer constraint: ")) 
     higher = int(raw_input("Enter a higher integer constraint: ")) 
     nums = gen_randoms(lower, higher) 
     this_equation = gen_equation(nums) 
     gen_answer = evaluate(this_equation) 
     if compare_answers(gen_answer): 
      correct += 1 
      print('You were right! Your winning streak is {0}'.format(correct)) 
     else: 
      print('Sorry, your answer was wrong. :(') 
      correct = 0 

     play_again = raw_input('Would you like to play again? (Y/N): ') 
Смежные вопросы