为什么Python用列表推导式初始化数组可行,但单独给元素赋值不行?
首先确认:你给出的写法(a)确实是列表推导式,属于Python中快速构造列表的语法糖。
两种写法的核心逻辑差异
你产生误解的核心原因是:arr=[0 for i in range(5)] 根本不是批量执行写法(b)的操作,二者的底层执行逻辑完全不同。
写法(a)的执行流程
你写的列表推导式代码,执行顺序是:
- 解释器先识别到你要生成一个基于
range(5)迭代的列表,首先会创建一个新的空列表对象,并且根据迭代器的长度(这里明确是5)预先申请好容纳5个元素的内存空间 - 遍历
range(5)的每一个元素,依次把计算得到的0写入新列表的对应位置,遍历完成后这个新列表的长度就是5 - 最后把这个已经构造完成的、长度为5的列表对象赋值给
arr变量(你之前写的arr=[]毫无作用,会直接被新列表覆盖)
整个过程中不存在给不存在的索引位赋值的操作,所以可以正常运行。
写法(b)的执行流程
- 执行
arr=[]后,arr是一个长度为0的空列表,此时没有任何合法的索引位置,允许的索引范围是空集 - 执行
arr[0]=0时,相当于你要给索引位0赋值,但这个索引位在当前长度为0的列表里根本不存在,Python的原生列表不支持跳空给未定义的索引位赋值,因此直接抛出IndexError: list assignment index out of range。
如果要实现类似的效果,你应该用arr.append(0)的方式追加元素,每次追加会自动在列表末尾新增位置,长度同步+1,不会触发越界。
其他初始化写法的逻辑说明
arr = [0]*5:本质也是直接构造一个长度为5的列表,预先分配对应空间后把所有位置赋值为0的引用,一次性完成构造,自然可以正常运行- numpy数组本质是固定大小的静态数组实现,初始化时指定长度后就会提前分配对应内存空间,所以支持直接给指定索引位赋值,和Python原生列表的动态扩容逻辑有本质区别。
内容的提问来源于stack exchange,提问作者jrive
相关产品推荐
相关产品推荐

