python - CPython 的解释器如何知道打印最后一个表达式的结果?

标签 python cpython python-internals

我一直在深入研究源代码,以找出打印结果的时间点。例如:

>>> x = 1
>>> x + 2
3

以上两条语句编译为:

  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE

  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_ADD
              7 RETURN_VALUE

第一个语句不打印任何内容,因为 None 是返回值。第二个返回加法的结果。

CPython 的交互式循环调用 PyRun_InteractiveOneObjectEx()对于每个输入。这gets the AST并调用 run_mod()compile that AST to byte code然后 evaluate the result在虚拟机中。 PyRun_InteractiveOneObjectEx() 获取的返回 Python 对象就是 top of the VM's stack .

到目前为止,所有这些都是我所期望的。但是返回值似乎是thrown away ! REPL 何时打印?

顺便说一句,我可以看到交互模式确实改变了分词器;它invokes PyOS_Readline使用 sys.ps1 提示符(默认为 ">>> ")。我在 pythonrun.c 中检查了类似的更改,但没有成功。

最佳答案

您正在展示通过将代码放入函数中生成的字节码的反汇编。这不是交互式代码的编译方式:它使用特殊的“单一”模式(compile() 的第 3 个参数,如果您在 Python 代码中执行相同的操作)。在这种模式下,丢弃每个表达式值的 POP_TOP 操作码变成了 PRINT_EXPRx = 1 什么都不打印的原因是语句在堆栈上没有留下任何需要弹出的东西,所以这个转换不适用。

关于python - CPython 的解释器如何知道打印最后一个表达式的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50374265/

相关文章:

python - 从不同的 JSON 文件创建语料库

python - 如何在 Databricks 的 PySpark 中使用 Scala 创建的 DataFrame

Python C 扩展不是线程安全的?

python - 为什么 2 个不同的 python lambda 具有相同的字节码?

python - 拆卸发电机会产生令人惊讶的结果

python - 使用函数的返回类型指定类型提示

python - 我如何通过特定的垃圾箱过滤数据框的行

python - Python的代码对象是什么类型?

python - Python嵌套操作的幕后花絮

python - __next__ 和 __str__ 是否由等效的 next 和 str 函数在内部调用?