Есть ли способ заставить пользовательские функции появляться в совершенно другом пространстве имен? - PullRequest
0 голосов
/ 03 мая 2019

Я пишу некоторый код для пакета исчисления в Python. В идеале я хотел бы поддержать композиции пользовательских функций. Например, пользователь может определить функции в моем классе SingleVariable следующим образом:

f = SingleVariable('sin(x)')
g = SingleVariable('x+4')

и затем композиция

h = SingleVariable('f(g(x))')

Эти функции могут быть интегрированы, дифференцированы и т. Д. Метод, используемый для оценки функции в точке, выглядит следующим образом:

def infix_to_function(infix, variable):
    def f(x):
        expression = infix.replace(variable, str(x)).replace('^', '**')
        return eval(expression)
    return f

Это прекрасно работает для таких функций, как sin и ln, потому что они могут быть загружены заранее, чтобы их можно было распознать с помощью eval. Однако это, очевидно, не работает для пользовательских функций, потому что они не существуют в пространстве имен, в котором функция фактически оценивается. Возвращаясь к примеру функций f и g, я хотел бы функцию, определенную как

h = SingleVariable('f(g(x))')

эквивалентно

h = SingleVariable('sin(x+4)')

Я пишу пакет в PyCharm и проверяю его, импортируя в Блокнот Jupyter. Я думал о добавлении функции в какой-то список при инициализации нового объекта SingleVariable, но для этого нужно каким-то образом получить имя переменной, которой он назначен.

Есть ли способ добавить функции, которые я определил в блокноте Jupyter, в пространство имен пакета PyCharm, чтобы они могли быть распознаны eval и иметь описанное поведение?

1 Ответ

0 голосов
/ 03 мая 2019

Вы можете попробовать передать globals() в eval, как eval(expression, globals()).Я полагаю, что Jupyter Notebooks поместит все функции, которые были определены, в глобальное пространство имен.

Однако использование exec () и globals () может вызвать много проблем - поэтому убедитесь, что вы действительно понимаете, что делаете,

Это будет немного сложнее, но если вы планируете сделать это очень общим, вы можете захотеть взглянуть на лексические библиотеки, такие как http://www.dabeaz.com/ply/example.html, которые помогут вам убедиться, что входные данные обеспечиваютявляется допустимым и анализируется правильно.

В качестве небольшого примера типа проблем, которые могут возникнуть - основываясь на вашем примере кода, я думаю:

f = SingleVariable('sin(s)')

может работать не так, как вы ожидаете...

...