Я интенсивно использую библиотеки числового анализа в Python, такие как подпрограммы оптимизации и интеграции Scipy, и многие из этих подпрограмм принимают обратный вызов, который оценивает какую-то целевую функцию в качестве основного аргумента.Из соображений производительности я часто реализую эти обратные вызовы в собственном коде (обычно с использованием Cython или Numba, которые генерируют код C, который компилируется, связывается и затем инкапсулируется в объекте Python).Многие подпрограммы Scipy теперь принимают экземпляр LowLevelCallable , который представляет собой такой объект, который содержит указатель на функцию C и информацию о ее сигнатуре.Если сама подпрограмма реализована на C или Cython, это может значительно сократить накладные расходы, полностью обходя интерпретатор Python.
То, что я пытаюсь выяснить, лучший способ сделать это - создать функции Python, которые принимают эти типынативные объекты обратного вызова, преобразовать их некоторым образом и вернуть другой собственный обратный вызов.Примером может служить функция, которая принимает обратный вызов, который прогнозирует y
с учетом x
вместе с массивом наблюдаемых значений y
, и возвращает другой обратный вызов, который вычисляет ошибку в прогнозах по сравнению с наблюдениями.Затем результат может быть передан в scipy.optimize.minimize()
.
Реализация для обычных функций Python будет выглядеть примерно так:
import numpy as np
def make_error_callback(f, y_obs):
def g(x):
y = f(x)
return np.sum((y - y_obs) ** 2)
return g
Цель состоит в том, чтобы, если f
было нативнымобратный вызов, который может быть оценен без вызова интерпретатора Python, тогда g
также должно быть.make_error_callback
, вероятно, должно быть реализовано в Cython или что-то подобное (в худшем случае фактический C с использованием Python C API).Фактические типы Python f
и g
будут представлять собой нечто, инкапсулирующее указатель на функцию C, например scipy.LowLevelCallable
.