在另一个函数中使用其值在一个函数中赋值的生成变量

Using generated variable whose value was assigned in one function in another function

新手python业余爱好者,第一次发题如果问题结构不规范请见谅

完整代码,如果您了解我想要实现的目标,请跳过介绍,并跳过前四个函数(如果您想执行完整代码,请提供它们)你这边):

import os, random
modes = ['Addition', 'Subtraction', 'Multiplication', 'Division']

global very_beginning, c_add, c_sub, c_mul, c_div, add_rounds, sub_rounds, mul_rounds, div_rounds, Round, correct, total_time

def mode_addition():
    num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
    print(num1, " + ", num2)
    return num1 + num2


def mode_subtraction():
    num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
    while num1 <= num2:
        num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
    print(num1, " - ", num2)
    return num1 - num2


def mode_multiplication():
    num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
    print(num1, " X ", num2)
    return num1 * num2


def mode_division():
    num2, num3 = random.randrange(1, 10), random.randrange(1, 10)
    num1 = num2 * num3
    print(num1, " ÷ ", num2)
    return num3


def mode_var_names(mode):
    return "mode_" + mode.lower() + "()", "c_" + mode.lower()[0:3], mode.lower()[0:3] + "_rounds"

def mental_math():
    print("Mental math game: ")
    global Round, correct, total_time, c_add, c_sub, c_mul, c_div, add_rounds, sub_rounds, mul_rounds, div_rounds
    Round, total_time = 1, 0
    correct, c_add, c_sub, c_mul, c_div, add_rounds, sub_rounds, mul_rounds, div_rounds = int(), int(), int(), int(), int(), int(), int(), int(), int()
    while Round <= 20:
        print('Round ' + str(Round), end=":\n\n")
        roundmode = random.choice(modes)
        mode_info = mode_var_names(roundmode)
        print("This round will be about:", roundmode)
        correct_answer = eval(mode_info[0])
        exec(mode_info[2] + " += 1")
        print("The answer is: ", end='')
        roundanswer = int(input())
        if roundanswer == correct_answer:
            print("The answer {} is correct.".format(roundanswer))
            correct += 1
            exec(mode_info[1] + " += 1")
        else:
            print("The answer {} is incorrect. The answer should be: {}".format(roundanswer, correct_answer))
        print("You got {} out of {} questions correct".format(correct, Round))
        user = input("Press enter to continue, or type 'stop' to end this quiz\n")
        if user == 'stop' or Round == 20:
            result_page()
            break
        Round += 1

def result_page():
    mark = round(correct / Round * 100)
    os.system('cls')
    print("Mental math game")
    print('FIN\n\n')
    print("You solved {} questions".format(Round))
    print("You got {}% of the questions correct.".format(mark))
    print("If you want detailed results type 'details'")
    print("If you want to continue, type 'again', else just close this windows or press Enter")
    user = input()
    if user == "details":
    for i in modes:
        print("In", i, "You got ", eval(mode_var_names(i)[1]), "correct answers out of ",
              eval(mode_var_names(i)[2]))

mental_math()

简介:

我正在整理一个心算游戏作为编码练习。它从字符串列表中随机选择模式:['Addition'、'Subtraction'、'Multiplication' 和 'Division'],使用它的名称调用创建问题的相应函数(例如,如果它选择加法,它会调用一个名为 mode_addition) 的函数,并跟踪每个模式的正确答案在每个模式总数中的数量,作为使用预定模板当场生成的变量(例如如果它选择加法,它将创建 2 个变量,分别称为 c_add(存储正确答案)和 add_rounds(存储涉及加法的总数 rounds/questions),如下所示:

modes = ['Addition', 'Subtraction', 'Multiplication', 'Division']
def mode_var_names(mode):
    return "mode_" + mode.lower() + "()", "c_" + mode.lower()[0:3], mode.lower()[0:3] + "_rounds" 
roundmode = random.choice(modes)
mode_info = mode_var_names(roundmode)

the return keyword returns a string containing the variable name which is then incremented through exec function

ex: exec(mode_info[1] + " += 1") increments the c_add if mode is addition

我将应用程序分解为 2 个主要功能,主要功能称为 mental_math(包含上述代码并生成变量),另一个称为 results_page(我调用一次在口译员处输入 'stop' 或解决 20 个问题)以显示我正确答对了每种模式的百分比和多少问题。

现在的问题:

我试图通过以下代码获取在 mental_math 处生成的变量以在 results_page 处打印它们的值:

for i in modes:
    print("In", i, "You got ", eval(mode_var_names(i)[1]), "correct answers out of ",
        eval(mode_var_names(i)[2]))

以及整轮的正确和总分return0:

In Addition You got  0 correct answers out of  0
In Subtraction You got  0 correct answers out of  0
In Multiplication You got  0 correct answers out of  0
In Division You got  0 correct answers out of  0

,而百分比 "mark = round(correct / Round * 100)" 是正确的。当我将打印循环复制回 mental_math 时,我得到了正确的数字(但我仍然想知道为什么原始状态不起作用)

到目前为止我尝试了什么

抛出的全局关键字是尝试获取 results_page 以获取模式变量的失败尝试(但为 Round 和 correct 变量做这项工作),我无法通过 eval()用于直接为全局生成变量名称的代码,我想过使用 return 方法但不知道如何在这种情况下使用它(并且宁愿只使生成的变量可访问)

我也尝试将它们组合在一起作为 class 希望所有变量都可以被其他函数或实例访问但是失败了,因为我才刚刚开始学习 OOP

更新与解决方案:

有(至少)2 个修复,Jason Nick Porter 的答案,并将 2 个函数添加到相同的 class

注意:我最终对此进行了大量编辑,因此随着您的进行它会变得越来越正确 :)

我将从放弃顶部的全局变量开始。全局变量是善变的情妇,我会不惜一切代价避免这种情妇。这是在 mental_math() fcn 中使用数组的好地方。在您当前拥有的函数内:

global Round, correct, total_time, c_add, c_sub, c_mul, c_div, add_rounds, sub_rounds, mul_rounds, div_rounds
Round, total_time = 1, 0
correct, c_add, c_sub, c_mul, c_div, add_rounds, sub_rounds, mul_rounds, div_rounds = int(), int(), int(), int(), int(), int(), int(), int(), int()

我只想说:

level, total_time = [1,0] # I put level instead of Round, since round is a keyword and could be confusing
correct = [0,0,0,0] # the index here corresponds to the mode
asked = [0,0,0,0]   # numpy.zeros would be an even more robust way to do this

这样每个变量都存在于函数内部,然后在mental_math()的末尾有这样的东西:

if user == 'stop' or level == 20:
    stats = [level, correct, total_time ] # and all the rest...
    result_page(stats)
    break

然后您拥有的所有统计数据都会传递给 results_page()。现在您需要将模式转换为元组而不是程序顶部的字符串。元组基本上是最好的,因为你可以 link 将不同类型的变量放在一起,像这样:

modes = [('Addition'       , 3 , 7), # These numbers correspond to where the correct
         ('Subtraction'    , 4 , 8), # and total numbers will be located in the stats
         ('Multiplication' , 5 , 9), # array.
         ('Division'       , 6 , 10)] # The spacing just makes it easier to see

现在您必须调整 results_page() 才能接收数组。然后,您可以通过索引访问所有值,而不是每个变量名。像这样:

def result_page(stats):
    mark = round(correct / stats[0] * 100)
    os.system('cls')
    print("Mental math game")
    print('FIN\n\n')
    print("You solved {} questions".format(stats[0]))
    print("You got {}% of the questions correct.".format(mark))
    print("If you want detailed results type 'details'")
    user = input("If you want to continue, type 'again', else just close this window or press Enter")
    # Fun-fact: If you pass a string to input() it prints it as a prompt
    if user == "details":
    for i in modes:
        print("In", i[0], " you got ", stats[i[1]], " correct answers out of ",
              stats[i[2]])

那你甚至不需要mode_var_names()

编辑:

好的,我没有意识到我的代码存在一些问题,所以上面的一些问题不是很好。我把它留在那里以防它有帮助。

下面的代码已更新,您可以根据需要添加任意数量的模式。问题是我没仔细看mental_math(),所以没发现它还在调用mode_var_names()。现在,它不再执行带有变量字符串的函数,而是将一个 int 传递给单个函数,并使用相同的 int 来决定在“正确”和“要求”数组中更新哪些数字。

import os
import random
import numpy as np

modes = [('Addition'       , 3 , 7), # These numbers correspond to where the correct
         ('Subtraction'    , 4 , 8), # and total numbers will be located in the stats
         ('Multiplication' , 5 , 9), # array.
         ('Division'       , 6 , 10)] # The spacing just makes it easier to see


def process(mode):
    # if you have more modes you want to add, just add more elif statements
    if mode == 0:
        num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
        print(num1, " + ", num2)
        return num1 + num2
    
    elif mode == 1:
        num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
        while num1 <= num2:
            num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
        print(num1, " - ", num2)
        return num1 - num2
    
    elif mode == 2:
        num1, num2 = random.randrange(1, 10), random.randrange(1, 10)
        print(num1, " X ", num2)
        return num1 * num2

    elif mode == 3:
        num2, num3 = random.randrange(1, 10), random.randrange(1, 10)
        num1 = num2 * num3
        print(num1, " ÷ ", num2)
        return num3

def mental_math():
    print("Mental math game: ")
    level, total_time = 0,0 # I put level instead of level, since level is a keyword and could be confusing
    
    correct = np.zeros(len(modes)) # the index here corresponds to the mode
    asked = np.zeros(len(modes))
    
    while level <= 20:
        level += 1
        print('Round ' + str(level), end=":\n\n")
        m = random.choice(range(len(modes)))
        print("This level will be about:", modes[m][0])
        
        correct_answer = process(m)
        asked[m] += 1
        
        levelanswer = int(input("The answer is: "))
        
        if levelanswer == correct_answer:
            print("The answer {} is correct.".format(levelanswer))
            correct[m] += 1
        else:
            print("The answer {} is incorrect. The answer should be: {}".format(levelanswer, correct_answer))
            
        print("You got {} out of {} questions correct".format(sum(correct), level))
        user = input("Press enter to continue, or type 'stop' to end this quiz\n")
        if user == 'stop' or level == 20:
            stats = np.hstack((level,sum(correct),total_time,correct,asked))
            result_page(stats)
            break
        

def result_page(stats):
    mark = round(stats[1] / stats[0] * 100)
    os.system('cls')
    print("Mental math game")
    print('FIN\n\n')
    print("You solved {} questions".format(stats[0]))
    print("You got {}% of the questions correct.".format(mark))
    print("If you want detailed results type 'details'")
    user = input("If you want to continue, type 'again', else just close this window or press Enter\n")
    if user == "details":
        for i in modes:
            print("In", i[0], " you got ", stats[i[1]], " correct answers out of ",
                  stats[i[2]])

mental_math()