我编写了一些代码来评估2d函数(具有2d输入和2d输出的函数),但我不知道如何将定义为字符串的方程式放入函数定义中。 例如,如果我有代码
eq = "x**2"
def func(x):
return eval(eq)
for i in range(100000):
print(func(i))
我需要评估的原因是因为我想要字符串版本,以便以后可以将其保存到csv文件中,而且我不想每次都必须在两个位置手动键入等式。因此,如果您运行此代码,它的运行速度将比:
def func(x):
return x**2
for i in range(100000):
print(func(i))
即使这些本质上是同一回事。所以我的问题是:在函数定义上,是否有办法像实际上将方程式插入到返回中一样,好像实际上是刚在其中键入该方程式一样?因为现在它只是进入eval()语句,查看字符串,然后对其进行求值,当我希望将方程式放入定义中并且每次遇到它时便知道它是什么,这需要很长时间。函数调用。
谢谢!
答案 0 :(得分:1)
如果函数仅由该方程式(即返回值)组成,而没有其他任何内容,则可以使用lambda
从方程式中创建它,如下所示:
def func_from_eq(eq):
return eval('lambda x : ({eq}, "{eq}")'.format(eq=eq))
func = func_from_eq("x**2")
func(3) # returns (9, "x**2")
它也使用eval
,但在创建函数时仅使用一次。之后,它像带有硬编码方程的def
一样被“编译”。
如果您的方程式不是完整的故事,即代码不止于此,您可以制作一个装饰器,该装饰器始终将定义的方程式添加到您的返回值中:
from functools import wraps
def add_eq(eq):
""" Decorator that packs the return value of a function
into a tuple together with the value eq (typically str). """
def decorator(func):
@wraps(func)
def wrapped(*args, **kwargs):
return func(*args, **kwargs), eq
return wrapped
return decorator
@add_eq("x**2")
def func(x):
return x**2
但是,是否非常漂亮尚待商discuss。它也有一个缺点,那就是您需要在代码和装饰器调用中多余地编写方程式,总是被迫使其保持同步。
答案 1 :(得分:0)
我在lambda中使用eval动态创建函数!
从源代码获取字符串,并使用lambda获取自定义函数
eqtn = "x+y*10"
fn = lambda x,y : eval(eqtn);
fn(x,y)
答案 2 :(得分:0)
如果您想提高eval
的执行性能,我认为您可以尝试lambda
的技巧:
In[1]: import random
In[2]: eq = "x**2"
# original time:
In[3]: % timeit random.random() ** 2
222 ns ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# use eval
In[4]: def func1(x): return eval(eq)
In[5]: % timeit func1(random.random())
5.7 µs ± 434 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# use lambda to accelerate
In[6]: func2 = eval('lambda x: ' + eq)
In[7]: % timeit func2(random.random())
273 ns ± 12.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
它接近原始代码,比eval
快20倍