2013-08-25 15 views
5

Attualmente sto usando una variabile globale nel mio codice chiamato correct. Considerando che i globals sono disapprovati, c'è un modo migliore per impostare il mio codice per "proteggere" la variabile globale?Python: codice Refactor per rimuovere la variabile globale

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

È un input e un ritorno da compare_answers()? – Jiminion

+0

Il modo più semplice è quello di allineare 'compare_answers()' a 'game()', e spostare anche la variabile 'correct' in' game() '. – Nayuki

+0

Inoltre, il fatto che tu stia usando la ricorsione di coda in 'game()' e 'compare_answers()' significa che a corto di spazio alla fine. – Nayuki

risposta

3

probabilmente lo farei qualcosa di simile:

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

Alcuni commenti:

  • Ogni funzione deve in genere solo fare una cosa, quindi se una funzione valuta un'equazione, è di solito è meglio non stampare anche l'equazione.
  • Capire dove le variabili dovrebbero andare diventa molto più facile quando si esegue questa operazione, dal momento che non è necessario passarle tanto quanto è necessario quando ciascuna funzione fa diverse cose.
  • La logica di gioco principale qui è sufficientemente semplice da non aver bisogno di romperla dalla funzione principale game() (o dalla funzione main(), nel mio esempio) così tanto da non complicare eccessivamente le cose per lasciarla lì . Se si volesse eseguire un altro controllo degli errori (ad esempio, se l'utente immette un numero non valido e si desidera tornare indietro e chiedere ulteriori input in tal caso), potrebbe essere opportuno scomporlo ulteriormente.
1

qualcosa di simile:

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

Aggiungi questa:

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 

quindi eliminare questi pezzi di vecchio codice: game(), compare_answers(), e la variabile globale correct.

0
  1. rimuovere il global correct da compare_answers
  2. impostato game a prendere in un argomento parola chiave correct con valore di default 0. def game(correct =0)
  3. impostato compare_answers di prendere un terzo argomento correct
  4. quando si chiama game da compare_answers passaggio nell'area correct

cioè:

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

Ho finito per prendere @ suggerimento di JoelCornett e la creazione di un classe:

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, mentre funziona, non è un buon OOP, ed è ancora solo un programma procedurale leggermente avvolto nella sintassi OOP. Ad esempio, tre dei cinque metodi (escluso '__init __()') non accedono a nessun dato di istanza o chiamano alcun metodo di istanza, il che suggerisce piuttosto che non appartengono alla classe. Rimuove il problema delle variabili globali, ma finisce per sostituire una cattiva pratica con un'altra. –

+0

Non è anche una cattiva pratica che il pacchetto '__init __()' chiami 'self.game()'? Dovresti separare 'game()' o 'run()' da '__init() __'. Puoi sempre dichiararlo ed eseguirlo (in modo anonimo) come un unico elemento con 'Math_Problem_Generator(). Run()' – smci

0

Raccogliere i risultati nel chiamante, quindi stampare il conteggio. Questa versione elimina gli altri globals, lower e 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): ')