最新理解 Python 的 for 循环_python for

2. 一个迭代器,

  1. 作为参数传递给next()方法时返回它的下一个元素或者在所有元素都遍历结束时抛  出StopIteration 异常。

  2. 作为参数传递给iter() 方法时返回它自身。

迭代协议仅仅只是一种将对象定义为迭代器的标准方式。我们已经在前一节看到了这种协议的实际应用。根据协议,迭代器应该定义以下两个方法:

  1. __next__()

1. 每次调用这个方法时,应该返回迭代器的下一个元素。一旦元素都遍历结束,它应该抛出StopIteration 异常。

  1. 当我们调动内置函数next() 时,实际内部调用的是本方法。

  2. __iter__()

1. 这个方法返回迭代器自身

  1. 当我们调动内置函数iter() 时,实际内部调用的是本方法。

自己写一个迭代器

现在我们已经知道迭代协议的原理,可以写一个自己的迭代器了。我们先看一个例子,下面我们创建了一个根据给定范围和步长的 Range 类。

我们看一下它在 for 循环中是怎么工作的。

注意,Range 类的实例是迭代器也是可迭代对象。

自己写一个可迭代对象

我们还可以基于 Range 迭代器另外创建一个可迭代对象。它的作用是每当调用 __iter()__ 方法是返回一个新的迭代器,在这里,它应该返回一个新的 Range 对象。

在 for 循环中使用我们这个 RangeIterable。

for 循环工作原理

现在我们已经知道什么是迭代器和可迭代对象,接下来了解一下 for 循环是如何工作的。

再看一下前面的例子。

当我们执行上面的代码块时,发生了以下这些事情:

  1. 在 for 语句内部对列表 [“You”, “are”, “awesome!”] 调用了 iter() 方法,返回结果是一个迭代器。

  2. 然后对迭代器调用 next() 方法,并将其返回值赋给变量 word。

  3. 之后,会执行 for 循环中关联的语句块。这个例子中是打印 word。

  4. 在 next() 方法抛出 StopIteration 之前会一直重复执行第 2,3 步。

  5. 一旦 next() 抛出 StopIteration,控制器会跳转到 else 子句(如果存在)并执行与 else 关联的语句块。

注意:如果在步骤 3 中,for 循环语句遇到了 break 语句,则跳过 else 代码块。

使用 while 语句实现 for 循环逻辑

我们可以像下面这样使用 while 语句实现之前的逻辑。

while 循环的行为实际上与 for 循环相同,上面的代码会有以下输出。

反编译 for 循环

在本节,我们将反编译 for 循环并逐步说明解释器在执行 for 循环时的指令。这里使用dis 模块来反编译 for 循环。详细来说,就是我们将使用 dis.dis 方法来生成可读性更高的字节码。

我们会使用之前一直用的简单 for 循环示例。接下来将文件写入文件 for_loop.py。

我们可以调用 dis.dis 方法获得可读性高的字节码。在终端上运行以下命令。

更多Python视频、资料、代码加群531509025免费获取

反编译输出的每列表示以下内容:

  1. 第 1 列:代码行数。

  2. 第 2 列:如果是跳转指令,则有 “>>” 符号。

  3. 第 3 列:以字节为单位的字节码偏移量。

  4. 第 4 列:字节码指令本身。

  5. 第 5 列:展示指令的参数。如果括号中有内容,它只是对参数做了更好的可读性转化。

现在我们来一步步浏览反编译后的字节码,并尝试了解实际发生了什么。

1. 第 1 行,即,“for word in [“You”, “are”, “awesome!”]:” 转译为:

0 SETUP_LOOP 28 (to 30)

该语句将 for 循环中的代码块推送到栈中。这段代码块会跨越 28 个字节,达到 “30”。

这意味着,如果 for 循环中有 break 语句,那么控制器将跳转到偏移位置 “30”。注意当遇到 break 语句时是如何跳过 else 代码块的。

2 LOAD_CONST 0 ((‘You’, ‘are’, ‘awesome!****’))

接下来,列表被推送到栈顶(TOS,之后使用 TOS 表示栈顶或栈顶元素)。

4 GET_ITER

该指令实现 “TOS = iter(TOS)”。这表示从列表获取一个迭代器(当前为 TOS),然后将迭代器推送给 TOS。

6 FOR_ITER 12 (to 20)

该指令获取 TOS,作为当前的迭代器, 并调用 next() 方法。

如果 next() 方法产生一个值,则将其作为 TOS 推送到栈,并执行吓一跳指令 “8 STORE_NAME”。

一旦 next() 表明迭代器已经遍历结束(即抛出 StopIteration 异常),TOS(迭代器)将从栈中弹出,字节码计数器会增加 12。这表示控制器跳转到指令 “20 POP_BLOCK”。

8 STORE_NAME 0 (word)

这个指令执行了转换 word = TOS,即,next()返回的值被赋给变量word

2. 第 1 行,即,“print(word)” 转译为:

10 LOAD_NAME 1 (print)

将可调用方法print 推送到栈中。

12 LOAD_NAME 0 (word)

将栈中的word作为参数推送给print

14 CALL_FUNCTION 1

调用带位置参数的函数。

像我们看到的指令那样,与函数关联的参数会出现在 TOS 中。在获得可调用象的对(如print)之前,会弹出所有遇到的参数。

一旦获得可调用对象,则把所有参数传递给它并调用。

可调用对象执行结束后,把返回值推送到 TOS 中,这里是 None。

16 POP_TOP

TOS(栈顶元素),即将函数的返回值从栈中移除(弹出)。

18 JUMP_ABSOLUTE 6

此时字节码计数器为 “6”,这表示下一条指令将执行 “6 FOR_ITER”。这是循环遍历迭代器中元素的方式。

注意,一旦迭代器中的元素都遍历结束,指令 “6 FOR_ITER” 会结束循环并跳转到 “20 POP_BLOCK”。

20 POP_BLOCK

POP_BLOCK 会从代码块的栈中移除由 “0 SETUP_LOOP” 设置的代码块。

3. **注意第 3 行(对应else),没有关联任何特殊指令。程序控制器会顺序执行下一条与else 相关的指令。

4. 第 4 行,即,*"print("See you later!“)”* 转译为:**

22 LOAD_NAME 1 (print)

推送与print 相关的可调用方法到栈中。

24 LOAD_CONST 1 (‘See you later!****’)

推送可调用函数的参数对象到栈中。

26 CALL_FUNCTION 1

可调用函数及其参数会从栈中弹出,然后执行函数并将其返回值推送到 TOS。

28 POP_TOP

TOS(栈顶元素),即将函数返回值(这里是 None)从栈中移除。

5.下面的两个指令只是简单的将脚本的返回值(None)加载到栈并返回。

30 LOAD_CONST 2 (None)

32 RETURN_VALUE

喔!现在我们已经了解了 for 循环反编译后的指令。希望这有助于更好地理解 for 循环的工作原理。

结尾给大家推荐一个非常好的学习教程,希望对你学习Python有帮助!

最后

Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

👉Python所有方向的学习路线👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

👉Python必备开发工具👈

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

👉Python全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

👉实战案例👈

学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。

因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。

👉大厂面试真题👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值