fo循环底层的执行逻辑是什么(fo循环的执行原理)
导语:for循环底层的执行逻辑
for循环的作用是用于遍历迭代对象,我们说的迭代对象比如list,dict,tuple,set,以及用户自定义的迭代器等。
可迭代对象
迭代:for循环来遍历过程的这种遍历就是迭代。
可迭代对象:是只实现了__iter__()方法的对象,能沟通__iter__()调用返回一个迭代器,并且可以通过迭代器的next()方法进行迭代访问的对象。
迭代器:
迭代器是一个可以记住遍历的位置的对象,所以他不需要将所有数据都加载到内存中,需要的时候去取即可。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
for循环底层的执行逻辑:
for i in data:print(i)
其中要求data是一个可迭代对象,for i in data:语句会返回一个迭代器,也就是会调用一个语句data.__iter__()返回一个迭代器,比如是it。
然后迭代器的指针就指向data这个地址开始位置。
之后每一次循环,都会执行it.__next__()方法取得它的下一个值,同时指针往后移动。
最后是一个异常处理,如果到了最后一个,没有数据可取了,那么会抛出一个StopIteration异常,结束迭代。这个异常不会跑给程序,由解释器自行处理。
for循环除了迭代到没有数据可取正常结束迭代之外,还有非正常退出,比如在for循环体中出现break和return语句。
其中return语句要求for循环是在函数中的,而break不需要。
这里再讲一个知识点,就是for循环能够绑定else一起使用,当for循环正常结束是会执行else中的代码块的,如果是break或return退出的话是不会执行else中的代码块。
a = [1,2,3,4]for i in b: if i == 2: print() breakelse: print()print()结果:break执行for循环之后的语句
变量赋值:
在python中,变量其实就是一个标识符,一个名称,一个内存的标记,比如a=2,其实是a指向2的内存地址,而我们在定义一个变量b=2,那么b也指向2的内存地址。
在看下下面这个例子,我们定义了一个列表a,然后再把a赋值给b,赋值过程其实就是b引用a,那么b和a指向同一个地址,如果我们接着将a重新赋值为a=[0],那么此时a指向了另一个内存地址,也就是说是另一个内存地址的标记,而b还是指向原来的地址。下面程序打印的结果就可以验证出来了。
a = [1,2,3,4]b = aprint(id(a),id(b))a = [0]print(id(a),id(b))结果:1435592027840 14355920278401435591981312 1435592027840
问题案例1:
a = [1,2,3,4,5]for i in a: print(i,a) a.remove(i) a = a[:]结果:1 [1, 2, 3, 4, 5]3 [2, 3, 4, 5]4 [2, 4, 5]5 [2, 5]
为什么是这个结果呢?
执行过程:
1.for循环for i in a执行了之后,产生了一个迭代器对象,迭代器指向a的内存地址;
2.然后执行next取下一个值,a.remove(i)删除了第一个元素1, 然后内存中(这不直接说a,是因为后面的a会变,内存不会变)的数据变成[2, 3, 4, 5],然后, a = a[:],执行的赋值语句,这是a指向了另一个内存地址,之后a的变化就不会再影响循环迭代了。
画个图说明下:
问题案例2:
a = [1,2,3,4,5]for i in a: print(i,a) if i in a: a.remove(i)print(a)结果:1 [1, 2, 3, 4, 5]3 [2, 3, 4, 5]5 [2, 4, 5][2, 4]
这个是a一直指向原来地址,但是a的元素删除了。
问题案例3:
a = [1,2,3,4,5]for i in a: print(i,a) a=[c for c in a if c!=i]print(a)结果:1 [1, 2, 3, 4, 5]2 [2, 3, 4, 5]3 [3, 4, 5]4 [4, 5]5 [5][]
这个a的地址变了,之后a和原来的地址已经没有关系了,原来列表地址中的元素也没有变。
本文内容由快快网络小故创作整理编辑!