Python:重构代码以删除全局变量

Python:重构代码以删除全局变量,python,refactoring,global-variables,Python,Refactoring,Global Variables,我目前正在代码中使用一个名为correct的全局变量。考虑到全局变量是不受欢迎的,有没有更好的方法来设置我的代码来“保护”全局变量 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: ")) corr

我目前正在代码中使用一个名为
correct
的全局变量。考虑到全局变量是不受欢迎的,有没有更好的方法来设置我的代码来“保护”全局变量

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()
大概是这样的:

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)  
添加以下内容:

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\u answers()
,以及全局变量
correct

  • compare\u答案中删除
    global correct
  • 设置
    game
    以使用默认值
    0
    接收关键字参数
    correct
    <代码>def游戏(正确=0)
  • 设置
    compare\u answers
    以获取第三个参数
    correct
  • compare\u答案中调用
    game
    传入
    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()
    

    我最终采纳了@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()
    

    我可能会这样做:

    #!/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()
      函数,在我的示例中)中分离出来,因此,将其保留在其中不会使事情过于复杂。如果您想做更多的错误检查(例如,查看用户是否输入了无效的数字,如果是,您想返回并要求更多的输入),那么您可能想再进行一些错误检查

    在调用者中收集结果,然后打印计数。这个版本摆脱了其他全局变量,
    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): ')
    

    将其作为一个输入并从compare_answers()返回?最简单的方法是将
    compare_answers()
    内联到
    game()
    ,并将变量
    correct
    移动到
    game()
    中。另外,在
    game()
    compare_answers()中使用尾部递归
    意味着您最终会耗尽堆栈空间。@NayukiMinase谢谢,您能解释一下“内联”是什么意思吗?消除全局变量的另一种方法是创建一个名为
    correct
    的实例变量的
    游戏类。这将限制
    correct
    .FYI的范围,虽然这是可行的,但它并不是很好的OOP,它仍然只是一个用OOP语法轻松包装的过程程序。例如,您的五个方法中有三个(不包括
    \uuu init\uu()
    )不访问任何实例数据或调用任何实例方法,这很明显表明它们不属于该类。它消除了全局变量问题,但最终以一种错误的做法取代另一种。让包的
    \uuu init\uuu()调用
    self.game()
    ,这难道不是一种错误的做法吗?您应该将
    game()
    run()
    \uuuu init()\uuuu
    分开。您仍然可以使用
    Math\u Problem\u Generator().run()