如何在不创建新列表的情况下过滤列表?遇UnboundLocalError求解决
解决UnboundLocalError及原地修改列表的方案
首先,咱们来拆解你遇到的两个核心问题:UnboundLocalError错误,以及不能创建新列表的约束。
1. 为什么会出现UnboundLocalError?
在Python函数内部,如果给一个变量赋值,Python会自动将其标记为局部变量。你的代码里,在individuals = list(filter(...))这行对individuals做了赋值,但在这之前(比如SeekWaterHole(individuals, lakes))已经使用了这个变量——此时Python认为individuals是局部变量,但还没被定义,所以抛出了错误。
2. 符合你需求的解决方案
你提到不能创建新列表,因为其他代码依赖原列表的引用。那我们需要原地修改原列表,而不是重新赋值一个新列表给individuals。
方案一:原地删除不符合条件的元素
替换你代码中这两段:
for r in range(len(individuals)): individuals[r].waterstore -= 1 individuals = list(filter(lambda x: x.waterstore > 0,individuals))
改成:
# 先给每个个体的waterstore减1 for individual in individuals: individual.waterstore -= 1 # 从后往前遍历删除waterstore<=0的元素(避免索引混乱) for idx in reversed(range(len(individuals))): if individuals[idx].waterstore <= 0: del individuals[idx]
这种方式直接修改原列表的内容,不会改变individuals变量的引用,其他依赖这个列表的代码会自动看到更新后的内容,同时也不会触发UnboundLocalError。
方案二:如果individuals是全局变量
如果individuals是在函数外部定义的全局变量,你也可以在函数开头声明它为全局变量,这样赋值操作就不会被视为局部变量:
def day(numberOfDays): global individuals # 声明为全局变量 days = 0 while days < numberOfDays: # 后续代码保持不变... individuals = list(filter(lambda x: x.waterstore > 0,individuals)) # ...
不过这种方式会让individuals指向新的列表对象,如果其他代码依赖的是原列表的引用,可能会出现问题——所以更推荐方案一的原地修改方式。
额外小建议
你原来的代码里计算individualTotalWater可以简化成列表推导式:
individualTotalWater = [i.waterstore for i in individuals]
这样更简洁高效~
内容的提问来源于stack exchange,提问作者Ole Kristian
相关产品推荐
相关产品推荐

