我正在写一个命令行计算器。我把所有的数学都记下来了,但我想添加自己的函数,比如solve(“x^3=8”,x)。我的数学很好,但是我使用exec()的方式阻止它将结果写入局部变量finalAnswer。你知道吗
我加入foo()来显示我想要的东西
def foo():
return 5
exec("a = foo()")
print(a)
result = "addAB(15,8)"
def addAB(A, B):
print(A+B)
return A+B
def __runFunc(fn, param):
exec("finalAnswer = fn(" + param + ")")
__approvedFunctions = set(["addAB", "subtractAB"])
funcName = result[:result.index('(')]
if(funcName in __approvedFunctions):
param = result[result.index('(')+1 : result.index(')')]
if callable(globals()[funcName]):
__runFunc(globals()[funcName], param)
print(finalAnswer)
执行时,我的输出是:
addAB(15,8)
5
23
Traceback (most recent call last):
File "C:/Users/mikeo/OneDrive/Documents/function filter.py", line 45, in
<module>
print(finalAnswer)
NameError: name 'finalAnswer' is not defined
输出的前三行告诉我脚本的每个部分都会执行,但是finalAnswer没有初始化。我错过了使用exec()的一些细微差别。你知道吗
另外,如果您帮助我删除exec而不更改调用参数化函数并在本地存储返回值的字符串输入的格式,则会获得额外的好处。你知道吗
这里可能不需要} ,它(顾名思义)可以计算包含有效Python文本的字符串。这使得它比普通的
exec
或eval
。如果您的表达式都很简单,就像您的示例代码中那样,那么我们可以不用使用^{eval
或exec
安全得多。当然,您的代码只尝试执行已批准的函数,因此它应该是安全的,但仍然。。。你知道吗不管怎样,这里有一个解决办法。我们将批准的函数存储在一个dict中,由函数名键入。我们假设包含函数参数列表的字符串是一个元组,并获取
literal_eval
来为我们构建元组,这样我们就可以使用*
序列解包将参数传递给函数。你知道吗输出
这是安全的,因为
ast.literal_eval
对于它在字符串中接受的内容非常严格。从文档中:容器显示是列表、元组、集合或dict文本,例如
(2,3,4)
或{'one':1, 'two': 2}
。如果您试图传递ast.literal_eval
包含函数调用甚至算术表达式的内容,例如或者
它将引发
ValueError: malformed node or string
这有个小例外。
ast.literal_eval
将接受只使用+
或-
的算术表达式。这是因为它需要能够计算复数文本,这些文本包含+
或-
。实现者认为,简单的处理方法是允许.literal_eval
计算包含+
或-
的算术表达式;这样做不会产生安全风险。不过,这只适用于算术表达式,不能使用+
进行字符串串联,因此将引发
ValueError
;OTOH,它不接受通常的相邻字符串文本的自动连接,因此这是正常的:相关问题 更多 >
编程相关推荐