Python VPython报错:createParticleAtom对象无electron属性
问题根因
你踩了几个非常基础的Python逻辑错误,之前尝试的修复方案完全没触及核心问题,所以一直没解决:
- 最直接的报错原因:电子根本没被创建。你写的电子生成循环用
for self.i in range(numberOfElectrons),传入numberOfElectrons=1时,range(1)生成的序列只有0,但你下面的判断条件是if self.i == 1才创建电子实例,这个分支永远进不去,self.electronList从头到尾是空列表。 - 你误以为在
updateAcceleration里定义了self.electron,但这个属性是在for self.electron in self.electronList循环里才会被绑定的——如果electronList是空的,循环根本不会执行,self.electron属性自然不存在。而且把循环变量直接绑定到实例属性本身就是不规范写法,多电子场景下这个属性只会保留列表最后一个电子的引用,逻辑完全错误。 - 动画循环里直接硬编码访问
self.electron,就算电子创建成功,多电子场景下也只会更新最后一个电子的运动状态,其余电子完全静止。 - 隐藏的经典Python坑:你在
__init__方法里用了可变默认参数electronList=[],这个列表会被createParticleAtom的所有实例共享,后续创建多个原子实例时,电子会被追加到同一个列表里,出现不同原子的电子串模的问题。 - 额外物理逻辑bug:你在动画循环外只计算了一次加速度,但库仑力是随电子和原子核的距离实时变化的,只算一次加速度会导致电子运动轨迹完全不符合物理规律。
修复方案
按以下步骤逐段修改代码即可解决问题:
- 修正
__init__方法的可变默认参数问题,把electronList的默认值改为None,在方法内部初始化空列表:def __init__(self, x, y, z, radius, defaultPosition=vector(0,0,0), frameOn=None, electronList=None): super().__init__() self.x = x self.y = y self.z = z self.radius = radius self.defaultPosition = defaultPosition self.frameOn = frameOn # 替换原来的self.electronList = electronList self.electronList = electronList if electronList is not None else [] self.createAtom(numberOfElectrons=1) - 修正电子创建的循环逻辑,不要用循环变量承接电子实例,单独用局部变量存储,同时修正下标判断错误:
把原来createAtom方法里的电子生成段替换为:if self.shellLayers == 0: for electron_idx in range(numberOfElectrons): if electron_idx == 0: electron = sphere(pos=vector(self.a0,0,0), radius=0.02*self.a0, velocity=vector(0, self.vE,0), mass=mE, charge=-e, color=color.blue) self.electronList.append(electron) elif electron_idx == 1: electron = sphere(pos=vector(-self.a0,0,0), radius=0.02*self.a0, velocity=vector(0, -self.vE,0), mass=mE, charge=-e, color=color.blue) self.electronList.append(electron) - 重写
updateAcceleration方法,去掉错误的实例属性绑定逻辑,改为接收单个电子对象作为入参,实时计算对应加速度:def updateAcceleration(self, electron): dr1 = electron.pos - self.Nucleon.pos Force1 = 1/(4*np.pi*self.e0)*self.Nucleon.charge*electron.charge/mag(dr1)**2 * norm(dr1) return Force1/electron.mass - 修正动画循环逻辑,遍历所有电子逐帧更新状态,每帧重新计算每个电子的加速度,删掉原来硬编码访问
self.electron的代码,同时删掉循环外一次性计算upAcc的代码:
这里可以直接删掉t = 0 tOrbit = 2*np.pi*self.a0/self.vE tEnd = 1000*tOrbit dt = tOrbit/1000. while (t<tEnd): rate(100) for electron in self.electronList: upAcc = self.updateAcceleration(electron) electron.velocity = electron.velocity + upAcc*dt electron.pos = electron.pos + electron.velocity*dt t = t + dtself.pi = np.pi的冗余赋值,全程直接用np.pi即可。
修复效果
改完后运行simulation.py会正常生成红色原子核与对应数量的蓝色电子,不会再触发AttributeError,电子会按库仑力作用围绕原子核运动。如果后续要添加更多壳层的电子,直接扩展对应壳层的电子生成逻辑即可。
内容的提问来源于stack exchange,提问作者KronosHedronos2077
相关产品推荐
相关产品推荐

