为什么Python for循环直接递增遍历值无法修改原列表的元素?
Python列表遍历修改差异原理说明
核心底层逻辑:Python的变量是「内存对象的标签」,且整数(int)是不可变类型
Python中所有变量本质都是绑定到内存对象的引用标签,不存在独立的“值变量”。而int属于不可变类型,一旦创建其内存存储的值就不能修改,所有对int的修改操作都会生成新的int对象,再把操作的变量标签绑定到新对象上。
两段代码的执行逻辑差异
1. 可成功修改列表的代码逻辑
numbers = [1, 2, 3] for number in numbers: numbers[numbers.index(number)] += 100
这段代码直接操作的是列表本身存储的引用标签:
- 代码通过
numbers[索引]的形式直接定位到列表内部存储元素的位置,执行+=100时,相当于把列表对应位置的原int对象标签解绑,重新绑定到新生成的加完值的int对象上,所以列表内容会发生变化。
*注意:该写法存在隐患,如果列表有重复元素,index()方法永远返回第一个匹配元素的索引,会导致修改逻辑出错,更稳妥的写法是配合enumerate遍历索引:
for idx, num in enumerate(numbers): numbers[idx] += 100 ```* ### 2. 无法修改列表的代码逻辑 ```python numbers = [1, 2, 3] for number in numbers: number += 100
这段代码操作的只是临时循环变量这个独立标签:
- for循环每次迭代,只是把列表中对应元素绑定的内存对象,同时绑定到临时变量
number这个标签上 - 执行
number += 100时,因为int是不可变类型,会生成一个新的int对象,把number这个临时标签重新绑定到新对象上,整个过程完全没有触及列表内部存储的引用标签,所以原列表不会有任何变化。
is判断返回True的原因
你做身份判断的代码是在number += 100之前执行的,此时临时变量number和列表对应位置的元素确实绑定的是同一个内存地址的int对象,所以is判断返回True。
如果在number += 100之后再做身份判断,就会返回False,可以用下面的代码验证:
numbers = [1, 2, 3] for number in numbers: print(numbers[numbers.index(number)] is number) # True number += 100 print(numbers[numbers.index(number)] is number) # False
内容的提问来源于stack exchange,提问作者barciewicz
相关产品推荐
相关产品推荐

