python - Python for 循环实际上是如何工作的?

标签 python for-loop python-internals

我很想了解 Python for 循环在幕后是如何工作的。我尝试像下面的代码片段一样实现它,for循环就是这样实现的吗?

my_list = [1, 2, 3, 4, 5]

# list itself is iterable but not iterator. Make it an iterator
iter_list = iter(my_list)

while True:
    try:
       print(next(iter_list))
    except StopIteration:
       break

最佳答案

是的,这非常接近 for循环构造被实现。它肯定符合 for loop statement documentation :

The expression list is evaluated once; it should yield an iterable object. An iterator is created for the result of the expression_list. The suite is then executed once for each item provided by the iterator, in the order returned by the iterator. Each item in turn is assigned to the target list using the standard rules for assignments (see Assignment statements), and then the suite is executed. When the items are exhausted (which is immediately when the sequence is empty or an iterator raises a StopIteration exception), the suite in the else clause, if present, is executed, and the loop terminates.

您只错过了使用标准分配规则分配给目标列表部分;你必须使用i = next(iter_list)print(i)而不是打印 next() 的结果直接打电话。

Python 源代码被编译为字节码,然后解释器循环执行。您可以查看字节码 for使用 dis module 循环:

>>> import dis
>>> dis.dis('for i in mylist: pass')
  1           0 SETUP_LOOP              12 (to 14)
              2 LOAD_NAME                0 (mylist)
              4 GET_ITER
        >>    6 FOR_ITER                 4 (to 12)
              8 STORE_NAME               1 (i)
             10 JUMP_ABSOLUTE            6
        >>   12 POP_BLOCK
        >>   14 LOAD_CONST               0 (None)
             16 RETURN_VALUE

命名的各种操作码记录在同一个 dis 中模块,其实现可以在 CPython evaluation loop 中找到(查找 TARGET(<opcode>) 开关目标);上述操作码分解为:

  • SETUP_LOOP 12 标记套件(一个语句 block )的开始,因此解释器知道在出现 break 时跳转到哪里,以及在出现异常或 return 的情况下需要执行哪些清理操作陈述;清理操作码位于此操作码之后 12 个字节的字节码(因此 POP_BLOCK 此处)。
  • LOAD_NAME 0 (mylist) 加载mylist变量值,将其放在堆栈顶部(操作码描述中的 TOS)。
  • GET_ITER 来电 iter() TOS 上的对象,然后用结果替换 TOS。
  • FOR_ITER 4 来电 next()在 TOS 迭代器上。如果给出结果,则会将其推送到 TOS。如果有StopIteration异常,则迭代器从 TOS 中删除,并且 4 个字节的字节码被跳到 POP_BLOCK操作码。
  • STORE_NAME 1 获取 TOS 并将其放入指定变量中,这里是 i .
  • JUMP_ABSOLUTE 6 标记循环体的结束;它告诉解释器返回到字节码偏移 6,即 FOR_ITER上面的说明。如果我们在循环中做了一些有趣的事情,那么这将发生在 STORE_NAME 之后,在 JUMP_ABSOLUTE 之前.
  • POP_BLOCK 删除 SETUP_LOOP 设置的 block 记账并从堆栈中删除迭代器。

>>标记是跳转目标,有视觉提示,可以在阅读跳转到它们的操作码行时更容易发现它们。

关于python - Python for 循环实际上是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54387889/

相关文章:

c - 我需要帮助理解这段 C 代码

python - 为什么在导入时会创建 .pyc 文件?

python - 如果字段在 Python 中为空,则返回 json 字段的优雅方法

python - 填充不保留所有列

python - 为什么 str.replace (在索引上)给出 KeyError?

python - 如何遍历列表中除最后一项之外的所有内容?

python - 一条一条运行时效果不错,循环使用时出错

python - DLL 加载失败 : The specified procedure could not be found. win32api、sys、os

python - 如何覆盖 Python 对象的复制/深度复制操作?

python 字典是指向...什么的指针的 HashMap ?