Взяв страницу из пьесы collection.namedtuple , вы можете использовать exec для "динамического" определения func
:
import numpy as np
import scipy.optimize as optimize
import textwrap
funcstr=textwrap.dedent('''\
def func(x, {p}):
return x * 2*a + 4*b - 5*c
''')
def make_model(**kwargs):
params=set(('a','b','c')).difference(kwargs.keys())
exec funcstr.format(p=','.join(params)) in kwargs
return kwargs['func']
func=make_model(a=3, b=1)
xdata = np.array([1,3,6,8,10])
ydata = np.array([ 0.91589774, 4.91589774, 10.91589774, 14.91589774, 18.91589774])
popt, pcov = optimize.curve_fit(func, xdata, ydata)
print(popt)
# [ 5.49682045]
Обратите внимание на строку
func=make_model(a=3, b=1)
Вы можете передать любые параметры, которые вам нравятся, make_model. Параметры, которые вы передаете make_model
, становятся фиксированными константами в func
. Все оставшиеся параметры становятся свободными параметрами, которые optimize.curve_fit
будет пытаться найти.
Например, выше, a = 3 и b = 1 становятся фиксированными константами в func
. Фактически, оператор exec
помещает их в глобальное пространство имен func
. Таким образом, func
определяется как функция x
и одного параметра c
. Обратите внимание, что возвращаемое значение для popt
является массивом длины 1, соответствующим оставшемуся свободному параметру c
.
Относительно textwrap.dedent
: В приведенном выше примере вызов textwrap.dedent
не нужен. Но в «реальном» сценарии, где funcstr
определяется внутри функции или на более глубоком уровне отступа, textwrap.dedent
позволяет писать
def foo():
funcstr=textwrap.dedent('''\
def func(x, {p}):
return x * 2*a + 4*b - 5*c
''')
вместо визуально непривлекательных
def foo():
funcstr='''\
def func(x, {p}):
return x * 2*a + 4*b - 5*c
'''
Некоторые люди предпочитают
def foo():
funcstr=(
'def func(x, {p}):\n'
' return x * 2*a + 4*b - 5*c'
)
но я нахожу цитирование каждой строки отдельно и добавление явных символов EOL немного обременительным. Однако это спасет вас от вызова функции.