学编程这么久了,大家不知道有没有想过一个问题,当我们执行Python时,它是怎么实现的呢?

众所周知,Python 是一门解释型的语言

——所谓“解释型”,当然是区别于以 C语言 为代表的编译型语言。编译型语言需要将整个程序文件全部转换为可以直接由机器执行的二进制文件;而解释型语言则是由相应的解释器一行一行“解释”并执行代码描述的行为。

正是因此,对于新接触的人来说,Python这样的解释性语言很多时候需要执行到相应的语句,才会发现一些显然的错误。

话说回来,Python的解释器是怎么样来“解释”Python代码的呢?

实际上,类似于Java的执行机制,Python也拥有自己的虚拟机。而这个虚拟机实际上执行的也是一种“字节码”。

在Python程序的执行中依然存在一个“编译”的过程:将Python代码编译为字节码。

并且,Python也提供了一个名为dis模块,用于查看、分析Python的字节码。

1. dis模块

举例来说,dis模块中有一个同名函数dis,可以用于将当前命名空间中的对象反汇编为字节码。

import dis

def add(add_1, add_2):

sum_value = add_1 + add_2

dis.dis(add)

执行结果为:

4 0 LOAD_FAST 0 (add_1)

2 LOAD_FAST 1 (add_2)

4 BINARY_ADD

6 STORE_FAST 2 (sum_value)

8 LOAD_CONST 0 (None)

10 RETURN_VALUE

其中,开头的数字“4”表示字节码的内容对应于脚本中第 4 行的内容。

随后的一列数字则表示对应指令所在的地址。纵向观察可以发现一个规律:下一条指令的地址总比上一条指令的地址大 2 。这是巧合吗?

显然不是的。官方文档《dis --- Python 字节码反汇编器》中记录的更改显示,从Python 3.6版本开始,”每条指令使用2个字节“。所以每条指令的地址会在上一条指令地址的基础上加2。

再往后,是一列表示指令含义的单词组合,实际上就是人类可读的对应指令名称。顾名思义,LOAD_FAST就是加载某个内容/对象到某处,”FAST“很可能意味着这是一个便捷快速的命令实现。

最右边,则是对应于当前命令的操作数,即操作对象。数字同样是一个类似于地址的表示,括号中的字符串则表示相应对象在Python代码中的具体名称。

这样我们就可以大概地阅读生成的字节码了:

首先Python将函数add的第一个参数add_1加载到某处,紧跟着将第二个参数add_2加载到第一个参数之后。然后调用了一个名为BINARY_ADD的指令,即对之前加载的两个参数做加法。再然后则是将加法所得的和sum_value存储在了另一个位置。最后,加载了一个常量None并返回。

其实读完上面这个执行过程,我们很容易想到一种常用的数据结构——栈。

像下面这样:

当然这并不是本文的重点——真要探讨Python的实现机制,还得另外写几篇长文才能说得一二。

使用dis.dis函数除了可以查看当前脚本中各个对象对应的字节码,还可以直接传入一段代码对应的字符串进行反汇编:

# test_dis.py

import dis

s = """

def add(add_1, add_2):

sum_value = add_1 + add_2

print("Hello World!")

import sys

"""

dis.dis(s)

汇编结果:

2 0 LOAD_CONST 0 (", line 2>)

2 LOAD_CONST 1 ('add')

4 MAKE_FUNCTION 0

6 STORE_NAME 0 (add)

5 8 LOAD_NAME 1 (print)

10 LOAD_CONST 2 ('Hello World!')

12 CALL_FUNCTION 1

14 POP_TOP

7 16 LOAD_CONST 3 (0)

18 LOAD_CONST 4 (None)

20 IMPORT_NAME 2 (sys)

22 STORE_NAME 2 (sys)

24 LOAD_CONST 4 (None)

26 RETURN_VALUE

2. compile函数

除了在程序中直接给出要反汇编的程序形成的字符串,我们还可以通过使用内置函数compile来形成相应脚本的编译对象,再使用dis.dis查看其字节码内容。

# test_compile.py

import dis

with open("test_dis.py", "r", encoding="utf-8") as f:

s = f.read()

compile_obj = compile(s, "test_dis.py","exec")

dis.dis(compile_obj)

字节码输出结果:

1 0 LOAD_CONST 0 (0)

2 LOAD_CONST 1 (None)

4 IMPORT_NAME 0 (dis)

6 STORE_NAME 0 (dis)

11 8 LOAD_CONST 2 ('\ndef add(add_1, add_2):\n sum_value = add_1 + add_2\n\nprint("Hello World!")\n\nimport sys\n')

10 STORE_NAME 1 (s)

13 12 LOAD_NAME 0 (dis)

14 LOAD_METHOD 0 (dis)

16 LOAD_NAME 1 (s)

18 CALL_METHOD 1

20 POP_TOP

22 LOAD_CONST 1 (None)

24 RETURN_VALUE

总结

dis模块为我们提供了一个观察Python内部机制的手段,恰当地使用dis模块,并结合其他方法,可以快速有效弄懂一些Python令人迷惑的地方。

希望大家善于利用这样一些有用的工具。

文章来源:公众号--Python技术 作者:轩辕御龙

以上就是W3Cschool编程狮关于 当你使用print时,Python是怎么运行的 的相关介绍了,希望对大家有所帮助。

python开始print_当你使用print时,Python是怎么运行的相关推荐

  1. python中syntaxerror什么意思_在Python中,“SyntaxError:调用'print'时缺少括号”是什么意思?...

    此错误消息表示您尝试使用Python 3来关注示例或运行使用Python 2 print 语句的程序: 打印"你好,世界!" 上面的语句在Python 3中不起作用 . 在Pyth ...

  2. python打开一个不存在的文件时-python判断文件是否存在,不存在就创建一个的实例...

    python判断文件是否存在,不存在就创建一个的实例 如下所示: try: f =open("D:/1.txt",'r') f.close() except IOError: f ...

  3. python语句first、*middles_Python语句print('%d%%%d'%(3/2, 3%2))的运行结果是( 1 )。_学小易找答案...

    [填空题]Python语句"print(tuple([1, 2, 3]), list([1, 2, 3]))"的运行结果是( 1 ). [单选题]Python语句序列: " ...

  4. python iterable对象_一篇文章看懂 Python iterable,

    Python 中的 iterable, iterator 以及 generator,一直是非常亲密但是难以区分的概念.nvie 有一个很好的 帖子阐述了它们之间的关系,但是内容偏向于概括和总结,对于新 ...

  5. python爬虫机器_Python常用的机器学习库|python爬虫|python入门|python教程

    https://www.xin3721.com/eschool/pythonxin3721/ Python在科学计算中用途广泛:计算机视觉.人工智能.数学.天文等.它同样适用于机器学习也是意料之中的事 ...

  6. 当我print时,Python做了什么

    文 | 轩辕御龙 来源:Python 技术「ID: pythonall」 写了这么久的程序,不知道大家有没有思考过,Python到底在干嘛呢? 或者换句话说,当我们执行Python代码的时候,是怎么实 ...

  7. print python excel分隔_合并/拆分 Excel?Python、VBA轻松自动化

    作者 | Ryoko 来源 | 凹凸数据 当你收集了 n 个人的 EXCEL 记录表,需要将它们汇成一个总表时你会怎么做呢? 如果不通过技术手段,要一个个打开再复制粘贴也太麻烦了吧! 此时就需要一个通 ...

  8. python控制台输出到文件_Python print 立即打印内容到重定向的文件

    看到本文标题也许要奇怪了,Python 的 print 难道不是也上可以看到结果的吗?在 Python shell 下只要 >> print('Hello world!') Hello w ...

  9. python编程常见的错误_Python编程时常见的3个错误

    当你做错事时,承认错误并不是一件容易的事,但是犯错是任何学习过程中的一部分,无论是学习走路,还是学习一种新的编程语言都是这样,比如学习 Python. 为了让初学 Python 的程序员避免犯同样的错 ...

最新文章

  1. JavaWeb学习总结(六)—HttpServletResponse
  2. mysql触发器对同一张表做操作_MySql 触发器对同表操作
  3. NOIP2013Day1T3 表示只能过一个点
  4. 用 Go 操作 MySQL 的 200 万数据时应该怎么搞?
  5. java生成UUID通用唯一识别码
  6. hadoop 多节点集群_设置Apache Hadoop多节点集群
  7. ObjC学习2-语法循环、条件,原来像学C语言一样啊!
  8. Jquery Ajax 异步设置Table中某列的值
  9. 连接linux工具Mtr,Linux/Windows MTR工具检测服务器性能详细方法
  10. 415 http请求 hutool_HTTP请求返回415错误码定位解决方法
  11. Linux的DNS深度学习(DNS服务器搭建)
  12. P4234(最小差值生成树 lct维护生成树)
  13. matlab imshow加画网格,matlab能生成随机行走网格吗? - 仿真模拟 - 小木虫 - 学术 科研 互动社区...
  14. 记一次CTFd平台搭建
  15. 异构网络互联(计算机网络)
  16. 【Python 3 的基础语法】
  17. 关于EasyRecovery工具数据恢复的原理
  18. Effective C++连载
  19. Android应该怎么学
  20. #内存泄露# #valgrind# valgrind简介

热门文章

  1. 如何解决java乱码_java如何解决乱码
  2. web服务器的文档根目录,web服务器根目录中
  3. golang MySQL 占内存_golang操作mysql使用总结
  4. 卸载一直在创建还原点_Win10电脑开机一直转圈无法进入系统的解决方法
  5. Python的模块化编程
  6. python 超时重试方法
  7. Python模块的四种形式
  8. 河南派出所犯罪嫌疑计算机网络人,【出彩河南公安人】息县公安局冯振娇:平凡岗位献青春 恒心不改展风采...
  9. 币对交易所_比特币向1万4大涨,OK交易所的比特币为什么反而贬值7折?
  10. ubuntu 编译c程序报错:对‘pthread_create’未定义的引用