Python:列表索引超出范围,不知道为什么

0 投票
2 回答
1003 浏览
提问于 2025-04-18 05:11

我正在尝试遍历一个矩阵,检查当前单元格周围有多少个相邻的单元格值为1。但是我遇到了一个越界的错误,我不太明白为什么会这样。

for x in range(0,ROWS):
    for y in range(0,COLS):

        #get neighbors
        neighbors = []
        if x!=0 & y!=COLS:
            neighbors.append([x-1,y+1])
        if y!=COLS:
            neighbors.append([x,y+1])
        if x!=ROWS & y!=COLS:
            neighbors.append([x+1,y+1])
        if x!=0:
            neighbors.append([x-1,y])
        if x!=ROWS:
            neighbors.append([x+1,y])
        if x!=0 & y!=0:
            neighbors.append([x-1,y-1])
        if y!=0:
            neighbors.append([x,y-1])
        if x!=ROWS & y!=0:
            neighbors.append([x+1,y-1])

        #determine # of living neighbors
        alive = []
        for i in neighbors:
            if matrix[i[0]][i[1]] == 1:
                alive.append(i)

我收到的错误信息是:

IndexError: list index out of range

这个错误出现在这一行 if matrix[i[0]][i[1]] == 1:

为什么会出现越界的情况,我该怎么解决呢?

2 个回答

3

编辑:我想我找到了问题

经过仔细检查你的代码,我发现你用的是 if x!=0 & y!=0。这里的 & 是按位与运算,而不是逻辑与运算,所以它不会给你想要的结果。你应该用 and 来代替 &,看看这样做是否能解决你的问题。

我建议稍微调整一下代码,这样会更容易阅读。

for loc_x in range(ROWS):
    for loc_y in range(COLS): # btw shouldn't ROWS/COLS be flipped?
                              # if your matrix isn't square this could be why
        x_values = [loc_x]
        if loc_x < ROWS: x_values.append(loc_x+1)
        if loc_x > 0: x_values.append(loc_x-1)
        y_values = [loc_y]
        if loc_y < COLS: y_values.append(loc_y+1)
        if loc_y > 0: y_values.append(loc_y-1)
        neighbors = [(x,y) for x in x_values for y in y_values if (x,y) != (loc_x,loc_y)]

        alive = [matrix[n[0]][n[1]] for n in neighbors if matrix[n[0]][n[1]]==1]

试着用你的代码运行这个,看看是否能解决问题。如果还是不行,你可能需要进一步测试。例如,可以把 alive 的定义放在 try/except 标签里,这样可以提供更好的错误追踪信息。

try:
    alive = ...
except IndexError:
    print("Location: {},{}\nneighbors: {}\nROWS:{}\nCOLS:{}".format(x_loc,y_loc, neighbors,ROWS,COLS))
    raise

顺便提一下,我之前解决这个问题的方法是创建一些对象来保存相关信息,然后从上到下、从左到右检查每个字段的右边和下面的字段。例如:

class Field(object):
    def __init__(self,x,y,value):
        self.x = x
        self.y = y
        self.value = value
        self.neighbors = neighbors

class Matrix(list):
    def __init__(self,size):
        self.ROWS,self.COLS = map(int,size.lower().split("x"))
        for y in range(ROWS):
            self.append([Field(x,y,random.randint(0,1)) for x in range(COLS)])
        self.plot()
    def plot(self):
        for row in self:
            for col in row:
                try:
                    self[row][col].neighbors.append(self[row+1][col])
                    self[row+1][col].neighbors.append(self[row][col])
                except IndexError: pass
                try:
                    self[row][col].neighbors.append(self[row][col+1])
                    self[row][col+1].neighbors.append(self[row][col])
                except IndexError: pass

当然,这样做并不能处理对角线的情况。不过我相信你能想出办法来处理这些问题!!

3

问题在于你使用了 &。这个符号是按位与运算,而不是逻辑与运算。在Python中,你应该用 and。比如:

if x!=0 and y!=COLS:
    neighbors.append([x-1,y+1])

不过,使用按位与运算造成问题的真正原因是运算顺序——它的优先级更高!

>>> 1 != 2 & 3 != 3
True
>>> (1 != 2) & (3 != 3)
False
>>> 1 != (2 & 3) != 3
True

所以即使你的逻辑看起来没问题,但运算顺序意味着你代码的实际行为和你预期的差别很大。

你代码的另一个问题是,你在检查 xy 是否等于 ROWSCOLS,而不是检查它们是否等于 ROWS-1COLS-1,后者才是真正的边界条件。

撰写回答