我有一个用户输入的数字数组。现在,我希望用户输入一个表达式(例如sin(x)),并希望使用数组中的数字来评估表达式。我不知道如何从用户获取表达式作为输入,然后基于数组对其求值。
到目前为止,我有:
collection = list()
number = input("Enter the number of elements you want: ")
for i in range(int(number)):
n = input("Enter number:")
collection.append(int(n))
print ('ARRAY: ',collection)
def function_creator():
expr = input("Enter the function(in terms of x):")
x = int(input("Enter the value of x:"))
safe_dict['x'] = x
y = eval(expr, {"__builtins__":None}, safe_dict)
print("y = {}".format(y))
if __name__ == "__main__":
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos',
'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor',
'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10',
'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt',
'tan', 'tanh']
safe_dict = dict([(k, locals().get(k, None)) for k in safe_list])
function_creator()
我曾尝试在python中使用eval()函数获取表达式,但无法使其正常工作。为了逐步进行操作,我现在不将数组用作用户输入的表达式中的x变量。相反,我只是尝试用用户选择的x评估用户输入的表达式。关于如何使其起作用的任何想法,或以其他方式可以将功能用作输入?]
此代码应适用于x中的表达式,例如x * sin(x)+(x + 1)* exp(2 * x)
from math import * # import sin, cos, tan, etc. into globals
# to allow use by eval
def function_creator(arr):
" allows expressions such as x*sin(x) + x "
expr = input("Enter the function(in terms of x):")
# x is bound locally inside the list comprehension for use by eval
return [eval(expr) for x in arr] # compute expression on each data element
if __name__ == "__main__":
collection = list()
number = input("Enter the number of elements you want: ")
for i in range(int(number)):
n = input("Enter number:")
collection.append(float(n))
print ('ARRAY: ',collection)
result = function_creator(collection)
print(result)
简单答案
您可以将函数导入全局范围,然后按如下所示从全局范围中获取它们:
from numpy import sin
collection = list()
number = input("Enter the number of elements you want: ")
for i in range(int(number)):
n = input("Enter number:")
collection.append(int(n))
print ('ARRAY: ',collection)
func_name = input("Enter function: ")
try:
ans = globals()[func_name](collection)
except KeyError:
raise AttributeError('Function not found in namespace!')
print(ans)
稍微复杂一些的答案
您可以尝试以下代码片段:
import numpy as np
collection = list()
number = input("Enter the number of elements you want: ")
for i in range(int(number)):
n = input("Enter number:")
collection.append(int(n))
print ('ARRAY: ',collection)
func_name = input("Enter function: ")
def getattr_loop(obj,attr):
'''getattr, or getitem, or error, in a loop, forever!'''
spl = attr.split('.')
if len(spl) > 1:
try:
return getattr_loop(getattr(obj,spl[0]),'.'.join(spl[1:]))
except AttributeError as err:
try:
return getattr_loop(obj[spl[0]],'.'.join(spl[1:]))
except KeyError:
raise err
else:
return getattr(obj,spl[0])
# Compute using user defined function
try:
ans = getattr_loop(globals(),func_name)(collection)
except AttributeError:
raise AttributeError('Function not found in namespace!')
print(ans)
getattr_loop
是将在obj
中递归搜索属性attr
的函数。 attr
给定的属性会自动读取点符号,因此您可以使用它来做一些漂亮的技巧。如果没有属性(.__getitem__()
)],它也可以进行一些处理以尝试obj[attr]
缺点是,getattr_loop
如果在RecursionError
中具有非常深层的嵌套属性,则会为您提供obj
。
例如,如果使用Numpy模块作为对象:
>>> getattr_loop(np,'random.rand')
这将允许您访问
np.random.rand
。如果按代码段中的方式使用globals()
,它将捕获在全局范围内定义的所有对象。因此,具有上述代码段的用户可以键入'np.sin'作为函数,并且该代码将计算np.sin(collection)
。
如果您希望直接使用sin
,则需要将其直接导入名称空间。
关于安全性的注意事项
globals()
中的东西从安全角度来看可能是冒险的。如果您需要此保护,请确保:
os.remove
之类的内容并造成一些伤害...享受!