python - CPython 的解释器如何知道打印最后一个表达式的结果?
问题描述
我一直在挖掘源代码以找出打印结果的时间点。例如:
>>> 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()
每个输入。这将获取 AST并调用run_mod()
以将该 AST 编译为字节码,然后在虚拟机中评估结果。获取的返回 Python 对象PyRun_InteractiveOneObjectEx()
只是VM 堆栈的顶部。
到目前为止,这一切都是我所期望的。但是随后返回的值似乎被丢弃了!REPL 什么时候打印出来的?
顺便说一句,我可以看到交互模式确实改变了标记器;它invokes PyOS_Readline
带有sys.ps1
提示(">>> "
默认情况下)。我检查了类似的变化pythonrun.c
,但没有运气。
解决方案
您正在显示通过将代码包含在函数中而生成的字节码的反汇编。这不是交互式代码的编译方式:它使用特殊的“单一”模式(compile()
如果您在 Python 代码中执行等效操作,则为 的第三个参数)。在这种模式下,POP_TOP
丢弃每个表达式的值的操作码会变成 a PRINT_EXPR
。什么都不打印的原因x = 1
是语句在堆栈上没有留下任何需要弹出的东西,所以这种转换不适用。
推荐阅读
- javascript - Javascript - 等待数组完成填充
- python - PyCharm 远程部署:未保存用户名
- ssl - 无法将 .CER 文件转换为 .PEM
- python - 从文本文件中读取整数,如果整数不在特定范围内,则激活 GPIO 引脚
- c++ - 如何在 C++ 上打印附加详细信息?
- c# - JSON文件中的Unity阿拉伯文本
- java - MVC SPRING HTTP 状态 500 - servlet mvc-dispatcher 的 Servlet.init() 抛出异常
- python - python2.x / 3.x中函数调用过长如何缩进
- excel - 根据第一列的值将列的值从一个工作表复制到另一个工作表
- java - 新机器上的多个 Java 可执行文件