如何解决对列表元素的更新适用于整个列表 python
我正在尝试编写一个简单的程序来使用 python(以及用于 GUI 的 pygame,因为我比 tk 有更多的经验)来模拟 N-Body 系统。我遇到的问题是我创建了一个主体类,它是精灵的子类。我有一个 n 的自适应列表大小,可以将许多主体附加到列表中。首先,我决定在一个双 for 循环中执行更新,最后一个 for 循环在计算后传递更新(我知道这效率不高,不是重点)。我的问题是,当我将更新传递给此列表的元素时,更新会应用于该列表中的所有内容。这里发生了什么?为什么将这些完全独立的元素捆绑在一起?下面是必要的代码
身体课
class Body(Sprite):
vel = Vector2(0,0)
acc = Vector2(0,0)
def __init__(self,x,y,size,mass,init_val = True,color=(255,255,0)):
super().__init__()
self.rect = Rect(x-size[0]/2,y-size[1]/2,size[0],size[1])
self.mass = mass
self.pos = Vector2(x,y)
#self.vel = Vector2(random(),random())
if init_val:
self.acc = Vector2(random(),random())
self.image = Surface(size)
self.image.fill((255,255))
self.image.set_colorkey((255,255))
draw_circle(self.image,color,(size[0]/2,size[1]/2),size[0]/2)
def update(self,force):
self.acc += force
self.vel += self.acc
self.rect.move_ip(self.vel)
模拟循环
class nbody:
def __init__(self,n = 3,screensize=(1366,768)):
self.win = pg.display.set_mode(screensize)
self.clock = pg.time.Clock()
self.bodies = Group()
sareax = [int(screensize[0]/4),int(screensize[0]*3/4)]
sareay = [int(screensize[1]/4),int(screensize[1]*3/4)]
c = [(255,0),(0,255)]
self.bodies = []
for i in range(n):
mass = 5 + random()*5
size = [mass*2]*2
self.bodies.append(Body(randint(sareax[0],sareax[1]),randint(sareay[0],sareay[1]),init_val=False,color=c[i]))
def run_sim(self,time=None,fps = 0.5):
run = True
while run:
self.clock.tick(fps)
self.win.fill((0,0))
for e in pg.event.get():
if e.type == pg.QUIT:
pg.quit()
quit()
elif e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
run = False
elif e.type == pg.KEYUP:
NotImplemented
updates = []
for b1,i in zip(self.bodies,range(len(self.bodies))):
df = Vector2(0,0)
for b2,j in zip(self.bodies,range(len(self.bodies))):
if i != j:
temp = newton(GRAV_CONSTANT,b1,b2)
mag = Vector2(b2.rect.centerx-b1.rect.centerx,b2.rect.centery-b1.rect.centery)
mag.scale_to_length(temp)
df += temP*mag
#print("Body {} has force {} to body {}".format(i,temP*mag,j))
if pg.sprite.collide_mask(b1,b2):
b1.kill()
b2.kill()
updates.append(df)
print(updates)
for bnum,up in zip(range(len(updates)),updates):
print("Before:",self.bodies[bnum].rect.center,self.bodies[bnum].vel,self.bodies[bnum].acc)
self.bodies[bnum].update(up)
print("Change:",up)
print("After:",self.bodies[bnum].acc)
pg.draw.line(self.win,(255,(20*up.normalize())+self.bodies[bnum].rect.center,width=2)
self.win.blit(self.bodies[bnum].image,self.bodies[bnum].rect)
pg.display.flip()
return
解决方法
见Class and Instance Variables:
一般来说,实例变量用于每个实例唯一的数据,类变量用于类的所有实例共享的属性和方法。
由于 val
和 acc
是类属性,因此它们由所有 Body
对象共享,正如您在问题中提到的:“这些完全独立的元素捆绑在一起”.
vel
和 acc
必须是 instance attribute 而不是 class attributes:
class Body(Sprite):
def __init__(self,x,y,size,mass,init_val = True,color=(255,255,0)):
super().__init__()
self.rect = Rect(x-size[0]/2,y-size[1]/2,size[0],size[1])
self.mass = mass
self.pos = Vector2(x,y)
self.vel = Vector2(0,0)
self.acc = Vector2(0,0)
if init_val:
self.acc = Vector2(random(),random())
self.image = Surface(size)
self.image.fill((255,255))
self.image.set_colorkey((255,255))
draw_circle(self.image,color,(size[0]/2,size[1]/2),size[0]/2)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。