【问题标题】:Using user defined variables/functions in eval [Python 3.4.2]?在 eval [Python 3.4.2] 中使用用户定义的变量/函数?
【发布时间】:2015-10-19 21:16:15
【问题描述】:

我有一个计算器(python 3.4.2),可以使用 eval 进行正常操作。

def calculator(user_input):
    if any(c not in config.valid_cal_chars for c in user_input):
        print("- Invalid Equation | Bad characters")
        return
    elif not any(c in user_input for c in "0123456789"):
        print("- Invalid Equation | No numbers found")
        return
    sys.stdout.write("calculating " + "-".join(gfx.load_sequence))
    time.sleep(0.1)
    print (" | 100%")
    try:
        current_ans = eval(user_input)
    except (SyntaxError, ZeroDivisionError, NameError, TypeError, ValueError):
        print ("- Invalid Equation | Error")
        return
    config.ans = current_ans
    print (current_ans)

这里是config.ans、config.valid_cal_char所指的config.py:

ans = ("0.0") 
valid_cal_chars = ("0123456789-+/*ansqrt() \n")

如果你想知道是什么

user_choice

变量指的是,它指的是我在这个函数之前的一个输入函数。该部分有效,因此无需担心。

但是,我想知道是否可以这样做:

input equation here: 4*4 #this would be saved as the user_input variable
> 16 #the output of the equation
input equation here: sqrt(ans) #this would use the previous answer saved in config.ans (ans) and the sqrt() to find the square root of the previous printed value, so:
> 4

所以键入 ans 会导致:

input equation here: 1+1
> 2
input equation here: ans
> 2

使用 sqrt() 会导致:

input equation here: 2+2
> 4
input equation here: sqrt(4)
> 2

所以如果还是不明白,sqrt() 求输入值的平方根。 ans 使用之前的返回值。因此,将两个“sqrt(ans)”结合起来将得到前一个返回值的平方根。

有了背景信息,我想做的是允许用户在计算时使用这些信息。虽然“eval”可能不起作用,但我也很乐意使用“exec”(知道危险)。但是,这里有一个 multitool.py(主文件),它导入这个文件(functions.py)来使用我在其中的所有功能,包括这个。

import os, sys, glob, math, random, login, gfx, config, functions, time

path = "******" #creates path to folder (can be changed by commenting this line out and creating new one)
dirs = os.listdir( path ) #not used currently

functions.load_sequence_complete()

functions.username_login()
time.sleep(0.05)
functions.password_login()
print ("\n[credentials have been verified! proceeding to main program " + "-".join(gfx.load_sequence) + "]\n")
time.sleep(0.1)

program = True
while (program == True):
    user_choice = functions.choice_selecter()
    functions.validate_choice(user_choice)

如果您需要任何其他信息,请将其放在下面的 cmets 或答案中,以便我可以对其进行编辑以帮助您:)

【问题讨论】:

    标签: python function python-3.x eval calculator


    【解决方案1】:

    你可以在第一种方法中做到这一点,你可以在函数的开头将ans定义为全局,然后是eval(user_input)的结果,并在任何地方使用ans而不是current_ans

    假设一切正常,你的函数会是什么样子 -

    def calculator(user_input):
        global ans
        if any(c not in config.valid_cal_chars for c in user_input):
            print("- Invalid Equation | Bad characters")
            return
        sys.stdout.write("calculating " + "-".join(gfx.load_sequence))
        time.sleep(0.1)
        print (" | 100%")
        try:
            ans = eval(user_input, {'ans':ans,'sqrt':sqrt},{})
        except (SyntaxError, ZeroDivisionError, NameError, TypeError, ValueError):
            print ("- Invalid Equation | Error")
            return
        config.ans = ans
        print (ans)
    

    请注意,我删除了函数中的 elif 部分,否则,它不会让像 - ans 这样的输入通过 - 你可能会重新考虑如何重写它。

    示例/演示 -

    >>> def calculator(user_input):
    ...     global ans
    ...     if any(c not in "0123456789-+/*ansqrt() \n" for c in user_input):
    ...         print("- Invalid Equation | Bad characters")
    ...         return
    ...     time.sleep(0.1)
    ...     print (" | 100%")
    ...     try:
    ...         ans = eval(user_input, {'ans':ans,'sqrt':sqrt},{})
    ...     except (SyntaxError, ZeroDivisionError, NameError, TypeError, ValueError):
    ...         print ("- Invalid Equation | Error")
    ...         return
    ...     print (ans)
    ...
    >>>
    >>> calculator('1+2')
     | 100%
    3
    >>> calculator('ans')
     | 100%
    3
    >>> from math import sqrt
    >>> calculator('sqrt(ans)')
     | 100%
    1.7320508075688772
    

    虽然你也可以使用eval作为 -

    ans = eval(user_input, {'ans':ans,'sqrt':sqrt},{})
    

    这将限制 eval 仅使用 anssqrt 作为名称。

    但您仍然应该重新考虑使用 eval() ,因为即使在其中限制了全局变量和局部变量之后,用户仍然可能造成伤害。为什么? Check here.

    【讨论】:

      【解决方案2】:

      出于多种原因,Eval 在这里不是一个好主意。虽然您可以通过调用轻松完成您所描述的操作:

      eval(user_input, {'ans': config.ans})
      

      您应该改为研究表达式的正确解析。 pyparsing 模块之类的东西应该可以帮助你。您可以在此处找到该项目的示例计算器:https://github.com/pyparsing/pyparsing/blob/master/examples/fourFn.py

      【讨论】:

      • 谢谢!我将检查 pyparsing 模块,但是 sqrt() 是如何在这里工作的呢?
      • Pyparsing 不再托管在 wikispaces.com 上。转至github.com/pyparsing/pyparsing
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多