Как вставить код в функцию, используя строковое уравнение?

Я запрограммировал некоторый код для оценки 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 x**2, 'x**2', когда он возвращает значение и фактическое строковое представление?

Matthew Barlowe 09.04.2019 07:25

Нет, я имею в виду, что я хочу, чтобы возврат был return x2, но eval занимает место x2, как если бы я набрал его в первую очередь

bayman21 09.04.2019 07:40

Итак, вы хотите динамически создать функцию из строки?

Blorgbeard 09.04.2019 07:52

Я думаю, что что-то вроде exec('def f(x): return x**2') действительно сработает.

Blorgbeard 09.04.2019 07:58
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
65
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если функция состоит только из этого уравнения, которое является возвращаемым значением, и ничего больше, вы можете создать ее из уравнения с помощью 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!

bayman21 10.04.2019 04:03

рад вам помочь :)

recnac 10.04.2019 04:14

Другие вопросы по теме