python源码深度剖析学习笔记十五
这篇文章主要总结python字节码相关的面试题
(一).python程序是如何运行的,是编译成字节码之后执行吗?
参考回答:
python是一种解释型语言,但是与shell这种脚本不太一样,python的执行原理更像是java,python解释器虽然被叫做解释器,但其实它包含编译器+虚拟机。python程序的运行过程如下
python解释器中的编译器将代码编译成代码对象,代码对象包含字节码以及执行字节码所需要的名字以及常量。
编译完成后,python解释器中的虚拟机维护执行上下文,逐行执行字节码指令。
和java不同的地方在于,java编译器javac与虚拟机java是分离的,而python将两者整合成一个python命令。java程序执行之前必须先完整编译,而python允许程序启动后再编译并加载需要的模块。
(二).python中的.pyc文件保存什么东西,有什么作用?
参考回答:
python程序执行需要先由编译器编译成代码对象后交给虚拟机执行,只要源码没有变化,编译后得到的代码对象就是一样的。python将代码对象序列化并保存到pyc文件中。当程序再次运行时,直接从pyc文件中加载代码对象,省去编译环节,当代码文件有改动时,python会重新编译。
(三).如何查看python的字节码?
参考回答:
python的内置模块dis,可以对代码对象及函数对象进行反编译,然后查看其字节码。例如:
importsysimportdisdis.dis(sys)就可查看sys模块的字节码了再例如defadd(x,y):...returnx+ydis.dis(add)就可以查看add的字节码了
(四).python中俩种交换变量的写法,有什么区别吗?哪种更优?
#写法一,解包组包a,b=b,a#写法二,中间量替换t=aa=bb=t
参考回答:表面上,第一种更简单优雅,更多细节可以通过字节码查看
#写法一10LOAD_NAME0(b)2LOAD_NAME1(a)4ROT_TWO6STORE_NAME1(a)8STORE_NAME0(b)#写法二10LOAD_NAME0(a)2STORE_NAME1(t)24LOAD_NAME2(b)6STORE_NAME0(a)38LOAD_NAME1(t)10STORE_NAME2(b)
可看到,第一种写法字节码指令更少,只需要使用ROT_TWO将两个变量做交换,ROT_TWO比LOAD_NAME、STORE_NAME更快。因此可以说第一种方式更优,原因:
1.代码简单,更加的pythonic
2.字节码指令只需要使用STORE_NAME将变量交换,比LOAD_NAME、STORE_NAME更快
3.不需要中间变量,节省内存
(五).python中的is和==操作有什么不同?参考回答:is是对象标识符,判断两个引用是不是同一个对象,等价于id(a)=id(b),==判断两个引用是不是相等,等价于调用魔法方法a.__eq__(b)。==操作符可以通过__eq__魔法方法进行覆写(overriding),而is操作符无法覆写。(下面有源码解释)从字节码上看,两者非常类似#aisb10LOAD_NAME0(a)2LOAD_NAME1(b)4COMPARE_OP8(is)6POP_TOP#a==b10LOAD_NAME0(a)2LOAD_NAME1(b)4COMPARE_OP2(==)6POP_TOP可以看到只是COMPARE_OP的操作数不一样,查看源码中COMPARE_OP指令处理逻辑的关键函数是cmp_out
转载请注明:http://www.sonphie.com/jbzd/14497.html