向嵌套列表append元素时同步修改所有列表?原因及修复方案
问题描述
我通过NewShip函数创建包含frontLeft、frontRight等6个嵌套列表的船舶对象,每个嵌套列表包含88个子列表,计划向子列表添加容器列表[id,20,2,cargo],每个子列表最多容纳18个容器。但调用loadContainerToShip函数执行添加操作时,容器会被插入到所有6个区域的嵌套列表中,且子列表内容是覆盖而非新增,请问问题原因是什么?如何修复?
相关代码
NewShip函数
def NewShip(length, width, height): frontLeft = [] #ship[5] frontRight = [] #ship[6] midLeft = [] #ship[7] midRight = [] #ship[8] backLeft = [] #ship[9] backRight = [] #ship[10] for i in range(88): x = []*18 frontLeft.append(x) frontRight.append(x) midLeft.append(x) midRight.append(x) backLeft.append(x) backRight.append(x) return [length, width, height, [], dict(), frontLeft, frontRight, midLeft, midRight, backLeft, backRight]
loadContainerToShip函数
def loadContainerToShip(ship,container): newWeight = container[4] lightestArea = getLightestArea(ship) #returns the index of the lightest area lightestStack = getLightestStack(ship[lightestArea]) #returns index of the lightest stack(list) loaded = False for i in range(len(ship[lightestArea][lightestStack])): #here i want to insert the new container if the container "below" in the tack is heavier oldWeight = getTotalWeightContainer(ship[lightestArea][lightestStack][i]) if oldWeight <= newWeight: #insertContainerOnShip ship[lightestArea][lightestStack].insert(i,container) ship[3].append(container) addContainerToDict(ship,container) loaded = True break if not loaded: print(ship[lightestArea][lightestStack]) ship[lightestArea][lightestStack].append(container) ship[3].append(container) addContainerToDict(ship,container)
问题原因
- 列表引用复用:在
NewShip的循环中,你创建了一个列表x,然后将同一个x对象重复添加到所有6个区域的列表中。Python里列表是引用类型,所有区域的子列表实际上指向同一个内存对象,修改其中任何一个子列表,其他区域对应的子列表都会同步变化,这就是容器被插入到所有6个区域的根本原因。 - 空列表初始化误区:
x = []*18不会创建一个最多容纳18个元素的列表,空列表乘以任何整数结果还是空列表。这行代码完全起不到限制容量的作用,不过这不是当前多区域同步修改的直接原因,但也是需要修正的逻辑漏洞。
修复方案
1. 修改NewShip函数,确保子列表独立
循环内不再复用同一个列表对象,每次都创建新的空列表,让每个区域的子列表都是独立的:
def NewShip(length, width, height): frontLeft = [] #ship[5] frontRight = [] #ship[6] midLeft = [] #ship[7] midRight = [] #ship[8] backLeft = [] #ship[9] backRight = [] #ship[10] for i in range(88): # 每次循环创建新的空列表,避免引用复用 frontLeft.append([]) frontRight.append([]) midLeft.append([]) midRight.append([]) backLeft.append([]) backRight.append([]) return [length, width, height, [], dict(), frontLeft, frontRight, midLeft, midRight, backLeft, backRight]
2. 添加子列表容量限制检查
既然要求每个子列表最多18个容器,需要在loadContainerToShip中添加容量判断,避免超出限制:
def loadContainerToShip(ship,container): newWeight = container[4] lightestArea = getLightestArea(ship) #returns the index of the lightest area lightestStack = getLightestStack(ship[lightestArea]) #returns index of the lightest stack(list) # 检查当前栈是否已满(最多18个容器) if len(ship[lightestArea][lightestStack]) >= 18: print("该栈已满,无法添加容器") return loaded = False for i in range(len(ship[lightestArea][lightestStack])): oldWeight = getTotalWeightContainer(ship[lightestArea][lightestStack][i]) if oldWeight <= newWeight: ship[lightestArea][lightestStack].insert(i,container) ship[3].append(container) addContainerToDict(ship,container) loaded = True break if not loaded: ship[lightestArea][lightestStack].append(container) ship[3].append(container) addContainerToDict(ship,container)
内容的提问来源于stack exchange,提问作者marfin
相关产品推荐
相关产品推荐

