Я запрограммировал некоторый код для оценки 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))
хотя по сути это одно и то же. Итак, мой вопрос: есть ли способ в определении функции на самом деле INSERT уравнения в возвращаемое значение, как если бы оно было на самом деле только что напечатано там в первую очередь? Потому что прямо сейчас он просто подходит к оператору eval(), просматривая строку, а затем оценивая ее, что занимает много времени, когда я хочу, чтобы он поместил уравнение в определение и просто знал, что это такое каждый раз, когда он встречается с вызов функции.
Спасибо!
Нет, я имею в виду, что я хочу, чтобы возврат был return x2, но eval занимает место x2, как если бы я набрал его в первую очередь
Итак, вы хотите динамически создать функцию из строки?
Я думаю, что что-то вроде exec('def f(x): return x**2')
действительно сработает.
Если функция состоит только из этого уравнения, которое является возвращаемым значением, и ничего больше, вы можете создать ее из уравнения с помощью 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
Но вопрос о том, красиво ли это, можно обсудить. У него также есть недостаток, заключающийся в том, что вам нужно писать уравнение избыточно, в коде и в вызове декоратора, всегда вынужденные синхронизировать их.
Я использую eval в лямбда для динамического создания функций!
Получите строку из вашего источника и используйте лямбда, чтобы получить свою пользовательскую функцию
eqtn = "x+y*10"
fn = lambda x,y : eval(eqtn);
fn(x,y)
если вы имеете в виду ускорение 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)
он близок к исходному коду, в 20 раз быстрее, чем eval
Я заставил его работать с eval("лямбда x:" + eq) большое спасибо! У меня время работы программы увеличилось примерно с 20 секунд до примерно 9!
рад вам помочь :)
Вы говорите о чем-то вроде этого
return x**2, 'x**2'
, когда он возвращает значение и фактическое строковое представление?