使用Python类求解耦合ODE时遭遇AttributeError问题求助
AttributeError: 'numpy.ndarray' object has no attribute 'rho' 解决方法——Scipy odeint与Python类结合问题
我来帮你排查这个问题,这个AttributeError的根源其实是几个小细节没处理好,咱们一步步来拆解:
问题核心原因
- 实例方法调用错误:你直接把
Mixer_model这个类方法传给了odeint,但没有通过Mixer_class的实例来调用它。这就导致odeint在调用这个方法时,把状态变量Z(numpy数组)当成了self参数传入,自然会出现“numpy数组没有rho属性”的错误——因为self被错误地赋值成了数组,而不是你的类实例。 - 函数签名不符合odeint要求:
scipy.integrate.odeint要求被求解的函数必须遵循func(y, t, *args)的签名,其中y是状态向量,t是时间变量。你的Mixer_model方法只定义了self和Z两个参数,缺少了t参数,即使前面的问题解决了,也会因为参数不匹配报错。 - 实例化顺序错误:你把
Mix = Mixer_class(...)放在了odeint调用之后,就算前面的调用方式正确,此时类实例还没创建,也无法访问实例属性。
修正后的完整代码
import numpy as np from scipy.integrate import odeint import matplotlib.pyplot as plt class Mixer_class: def __init__(self, rho, F1, F2, F, x1,x2): self.rho = rho self.F1 = F1 self.F2 = F2 self.F = F self.x1 = x1 self.x2 = x2 # 修正方法签名:增加t参数(即使不用也要保留,因为odeint会自动传入) def Mixer_model(self, Z, t): dXdt = (1/(self.rho*Z[1]))*(self.F1*(self.x1-Z[0]) + self.F2*(self.x2-Z[0])) dVdt = (1/self.rho)*(self.F1 + self.F2 - self.F) return [dXdt, dVdt] # 1. 先实例化类,确保实例在使用前创建 Mix = Mixer_class(1000, 12.5, 6.7, 3.87, 0.42, 0.58) t = np.arange(0,650, 22.5) # initial condition V0 = 0.75 # m^3 x0 = 0.95 Z0 = [x0, V0] # 2. 调用odeint时,传入实例的Mixer_model方法 Vx = odeint(Mix.Mixer_model, Z0, t) plt.plot(t,Vx[:,0],'ko--',linewidth = 1.5, label='X(t)') plt.plot(t,Vx[:,1],'cs-',linewidth = 1.5, label='V(t)') plt.ylabel('V(t) and X(t)') plt.xlabel('Time(sec)') plt.legend() plt.show()
关键修改点说明
- 调整实例化顺序:把
Mix = Mixer_class(...)移到odeint调用之前,保证使用实例方法时实例已经存在。 - 修正方法签名:给
Mixer_model增加t参数,符合odeint的函数要求(即使你的模型不依赖时间,这个参数也必须保留,因为odeint会自动把当前时间传入)。 - 正确调用实例方法:用
Mix.Mixer_model代替直接写Mixer_model,这样self参数会自动绑定到Mix这个实例,就能正确访问self.rho、self.F1等属性了。
额外优化
我还给你的绘图代码加了label和legend,这样能更清晰地区分两条曲线的含义,方便查看结果。
内容的提问来源于stack exchange,提问作者Jeddouibi
相关产品推荐
相关产品推荐

