在下面显示的情况下,我有一个名为func1()
的函数,它位于func3()
,其中func3()
使用Euler方法求解ODE的值。
def func1(x, y):
return y * np.log(y) / x
def func3(x, y, step_size, func):
dydx = func(x, y)
new_x = x + step_size
new_y = y _ step_size * dydx
return new_x, new_y
step_size - 0.1
lower = 2.0
upper = 3.0
e = 2.7182828284
x_val = [2.0]
y_val = [e]
for i in range(10):
x, y = func3(x_val[i], y_val[i], step_size, func1)
x_val.append(x)
y_val.append(y)
代码将func1作为装饰器传递给func3,并将输出写入列表,因为它在0到10的范围内迭代。但是,func3()
中的代码硬编码为func1()
的确切输入,即x
和y
。我想写func3()
足够通用,你可以传递任何函数,只要它的前两个输入是x
和y
,但它应该是更多输入的cabaple。所以假设上面显示的所有代码都是相同的,但是我没有通过func1()
,而是将func2()
传递给func3()
,其结构如下所示。
def func2(x, y, z):
return z * y * np.log(y) / (x*z)
我怎么能写func3()
足够通用它可以采取两个函数中的任何一个,并理解他们是更多的参数传递给func1()
,这也必须传递到func3()
?
您可以使用Python的可变长度参数语法来等待任何额外的参数,并传递它们。如果没有,它仍然可以工作:星号变量将接收空列表作为其值,并且在秋天扩展到func
时将消失。
def func1(x, y):
return x+y
def func2(x, y, z):
return (x+y)*z
def caller(func, x, y, other, other2, *args):
return func(x, y, *args)
使用*args
和**kwargs
收集参数(除了用于回调的x
和y
):
def func3(x, y, step_size, func, *args, **kwargs):
dydx = func(x, y, *args, **kwargs)
...
但是,考虑一下func3
真的有必要调用func
本身;让呼叫者改为做。
def func3(x, y, step_size, dydx):
new_x = x + step_size
new_y = y - step_size * dydx
return new_x, new_y
for old_x, old_y in zip(x_val, y_val):
x, y = func3(old_x, old_y, step_size, func1(x, y))
...
最好使用* args和** kargs(python中的函数定义中的** kwargs用于传递一个keyworded,可变长度的参数列表。我们使用名称kwargs和双星。原因是因为双star允许我们传递关键字参数及其中的任意数量)。
例如:
def myFun(arg1,arg2,arg3):
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
args =(“嘿”,“嗨”,“再见”)
myFun(*参数)
kwargs = {“arg1”:“极客”,“arg2”:“书呆子”,“arg3”:“Noob”}
myFun(** kwargs)
输出:嘿嗨再见Geek Nerd Noob
我不认为你真的需要接受除x和y之外的其他参数或改变func3。
我们假设你想把z传递给内部函数。而且你还需要将它传递给func3。由于z在func3调用期间不会改变,你可以像func3(x, y, lambda x, y : your_func (x, y , z), step)
这样做,并通过lambda接受x和y使用任意数量的参数。
在你的情况下,电话会看起来像:
x, y = func3(x_val[i], y_val[i], step_size, lambda x, y: func2(x, y, 111))