Python Actor类move方法操作self.coords时错误增减2而非预期1
异常产生原因
问题的核心是Python中列表属于可变引用类型:canmove方法内的moving = self.coords语句,没有创建坐标列表的独立副本,只是给原本的self.coords列表新增了一个别名引用,两者指向内存中同一个列表对象。
对应move('down')的实际执行流程:
- 进入
canmove('down')逻辑,执行moving[1] +=1时,会直接修改原self.coords的取值,此时初始坐标[2,2]已经被改为[2,3] canmove完成校验返回True后,move方法会对self.coords[1]再执行一次+=1操作
两次叠加的修改最终让坐标从[2,2]变为[2,4],也就是实际变动幅度是预期的2倍。
之前你认为canmove不会干扰最终结果的判断,是因为没有考虑到可变对象引用传递的特性——对别名变量的修改会直接作用在原对象上。你感知到“跳过canmove校验依然有异常”,本质是canmove被调用的过程已经在无感知的情况下修改了原坐标值,并非move方法内的坐标增减逻辑本身存在错误。
修复方案
只需在canmove方法中,获取待校验的移动坐标时创建独立副本,切断和原self.coords的引用关联即可。
将原代码中canmove方法的第一行moving = self.coords,替换为任意一种列表副本写法:
moving = self.coords.copy()- 或
moving = self.coords[:]
修改后的canmove方法核心逻辑示例:
def canmove(self, direction): # 创建坐标副本,校验过程不改动原self.coords的值 moving = self.coords.copy() if(direction == 'up'): moving[1] -= 1 elif(direction == 'right'): moving[0] += 1 elif(direction == 'down'): moving[1] += 1 elif(direction == 'left'): moving[0] -= 1 if((moving[0] > self.limits[0]) or (moving[1] > self.limits[1]) or (-1 in moving) or (moving in self.barriers)): return False else: return True
修改后再执行复现流程,调用actor.move('down')时,canmove的内部修改只会作用在独立的坐标副本上,仅用来做移动合法性校验,不会改动原坐标,最终坐标会按预期从[2,2]变为[2,3]。
内容的提问来源于stack exchange,提问作者João H. L. Corrêa
相关产品推荐
相关产品推荐

