python中list越界不报错的语法陷阱

这几天我的一个程序出了一个不会报错的莫名其妙的bug。
我把这个问题以最简化的代码复现如下:

class AA():
    def __init__(self):
        super(AA, self).__init__()

    def __getitem__(self, item):
        a = [1, 2, 3]
        b = a[999]  # list索引越界
        return b


aa = AA()
out = []
for b in aa:
    out.append(b)
    if len(out) >= 10:
        break

print(out)

正常list索引越界问题解释器会报错的, 但是这段代码不报错,会打印一个空列表出来。每次for循环都会执行0次直接跳出循环,而且解释器不报出任何错误信息,如果程序较为复杂,寻找bug过程会相当艰辛。
其实这里是一个for循环运行机制导致的语法陷阱,所以要弄清楚这个问题的深层次原因我们要先弄清楚for循环的运行机制:【python中for循环的运行机制

现在回到上边代码的bug问题,语法陷阱是这样产生的:

  1. for语句调用内置方法iter(aa)得到了一个临时迭代器
  2. 程序执行到b = a[999] # list索引越界 这行的时候抛出了索引越界异常:IndexError
  3. 临时迭代器捕获到这个异常后当作数据索引完毕的信号而并没有处理这个异常(这就是问题的关键),随后迭代器抛出异常:StopIteration
  4. for语句捕获到StopIteration后结束了循环

整个过程没有一个报错,list索引越界异常被完美隐藏。

这个问题从出现到难以查找bug的原因是对python的内部运行原理不够深入了解,但我相信很多人和我一样把python当作开箱即用的编程语言,没有花很多时间去深入学习它,这也是python一个优点。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值