Python传递带参函数作为另一函数参数时遇TypeError问题求助
问题:高斯积分传递被积函数时触发TypeError
我在WKB函数中尝试将integrand函数以int_gauss(integrand(E,x0,m1,x),xp,wp)的形式传入int_gauss作为参数,收到如下错误:
TypeError: 'numpy.ndarray' object is not callable
我已经通过在int_gauss内直接实现integrand的计算逻辑得到了预期结果,但希望能实现将integrand作为参数传入int_gauss的调用方式。
原报错代码
x0=1 m1=1 h=1 e=100 import numpy as np import matplotlib.pyplot as plt def gaussxw(N): a = np.linspace(3,4*N-1,N)/(4*N+2) x = np.cos(np.pi*a+1/(8*N*N*np.tan(a))) # Find roots using Newton's method epsilon = 1e-15 delta = 1.0 while delta>epsilon: p0 = np.ones(N,float) p1 = np.copy(x) for k in range(1,N): p0,p1 = p1,((2*k+1)*x*p1-k*p0)/(k+1) dp = (N+1)*(p0-x*p1)/(1-x*x) dx = p1/dp x -= dx delta = max(abs(dx)) # Calculate the weights w = 2*(N+1)*(N+1)/(N*N*(1-x*x)*dp*dp) return x,w def gaussxwab(N,a,b): x,w = gaussxw(N) return 0.5*(b-a)*x+0.5*(b+a),0.5*(b-a)*w N = 50 x, w = gaussxw(N) def integrand(E,x0,m1,x): return np.sqrt((2*m1*(E- (e*( ((x0/x)**12) -2*((x0/x)**6) ) )))) def WKB(E,x0,e): a, b = x0*(1+np.sqrt(1+(E/e)))**(-1/6), x0*(1-np.sqrt(1+(E/e)))**(-1/6) xp = 0.5*(b - a)*x + 0.5*(b + a) wp = 0.5*(b - a)*w return int_gauss(integrand(E,x0,m1,x),xp,wp) def int_gauss(f,nodes, weights): result = 0.0 for x, w in zip(nodes, weights): result += w *f(x) return result plt.close() En=np.linspace(-100,-1,496) W=[WKB(i,x0,e) for i in En] plt.figure() plt.plot(En,W) plt.grid() plt.axis() plt.show()
已实现功能的代码(但未传递函数参数)
def WKB(E,x0,e): a, b = x0*(1+np.sqrt(1+(E/e)))**(-1/6), x0*(1-np.sqrt(1+(E/e)))**(-1/6) xp = 0.5*(b - a)*x + 0.5*(b + a) wp = 0.5*(b - a)*w return int_gauss(E,x0,m1,xp,wp) def int_gauss(E,x0,m1,nodes, weights): result = 0.0 for x, w in zip(nodes, weights): result += w * np.sqrt((2*m1*(E- (e*( ((x0/x)**12) -2*((x0/x)**6) ) )))) return result
解决方案
错误原因
integrand(E,x0,m1,x)会直接执行函数,返回一个numpy数组,而int_gauss需要的是一个可调用的函数(能接收x参数并返回对应值),所以触发了"numpy数组不可调用"的错误。
修复方法
需要将E、x0、m1这些固定参数绑定到integrand上,生成一个只需要接收x参数的可调用函数,有两种简单实现方式:
方法1:使用lambda表达式
修改WKB函数中的调用代码:
def WKB(E,x0,e): a, b = x0*(1+np.sqrt(1+(E/e)))**(-1/6), x0*(1-np.sqrt(1+(E/e)))**(-1/6) xp = 0.5*(b - a)*x + 0.5*(b + a) wp = 0.5*(b - a)*w # 用lambda绑定固定参数,生成仅接收x的函数 return int_gauss(lambda x_val: integrand(E, x0, m1, x_val), xp, wp)
方法2:使用functools.partial
先导入partial,再修改WKB函数:
from functools import partial def WKB(E,x0,e): a, b = x0*(1+np.sqrt(1+(E/e)))**(-1/6), x0*(1-np.sqrt(1+(E/e)))**(-1/6) xp = 0.5*(b - a)*x + 0.5*(b + a) wp = 0.5*(b - a)*w # 绑定固定参数,生成可调用的函数对象 bound_integrand = partial(integrand, E, x0, m1) return int_gauss(bound_integrand, xp, wp)
两种方法都能让int_gauss接收到一个可调用的函数,在循环中调用f(x)时,会自动用当前的节点值x去计算对应的被积函数值,最终完成高斯积分计算。
内容的提问来源于stack exchange,提问作者VisCCelludamtan
相关产品推荐
相关产品推荐

