微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对列表元素的更新适用于整个列表 python

如何解决对列表元素的更新适用于整个列表 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

一般来说,实例变量用于每个实例唯一的数据,类变量用于类的所有实例共享的属性和方法。

由于 valacc 是类属性,因此它们由所有 Body 对象共享,正如您在问题中提到的:“这些完全独立的元素捆绑在一起”.

velacc 必须是 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 举报,一经查实,本站将立刻删除。