理解 Python 的执行方式,与字节码 bytecode 玩耍 (下)

上次写到,Python 的执行方式是把代码编译成bytecode(字节码)指令,然后由虚拟机来执行这些 bytecode

而 bytecode 长成这个样子:  b'|\x00\x00d\x01\x00\x14S' 。显然这个样子适合机器看,不适合人类看。 

虽然你可以通过查字典的方式,手动把这段 bytecode 编写成人类可以看得懂的样子,

但是这么劳累的事情,为什么要自己亲手来做呢,让你的男仆机器来做不就好了吗。

 

Python 的反汇编工具 dis 就可以办到这件事。下面用绚丽的紫色来对dis.dis 的输出结果进行分列解释。

>>> def double(a):
    return a*2  # 并不知道为什么贴在这里缩进会是这样

>>> import dis
>>> dis.dis(double)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 (2)
              6 BINARY_MULTIPLY
              7 RETURN_VALUE

上一篇文章的末尾已经解释过了,第2列的数字 0 3 6 7 是 bytecode 的偏移量。

第3列很好理解,都是opcode。注意这些 opcode 是给弱弱的人类看的,不是给机器看的,机器只要看b'|\x00\x00d\x01\x00\x14S' 这种东西就行了),

比如第一个opcode, 大名叫做叫LOAD_FAST,查一下资料,发现它的意思是 Pushes a reference to the local co_varnames[var_num] onto the stack.

中文意思:把本地某个东西的引用压到栈里。

什么东西呢?那就是 co_varnames[var_num] 啦。

(内心OS: 看这形象似乎是列表或者字典,字符串不太可能,自定义对象更不可能……)

 

>>> double.__code__.co_varnames[0] # 第4列里的下标 0
'a' 
>>> double.__code__.co_consts[1] # 第4列里的下标 1
2

上次讲过了:double 是函数对象 function object

double.__code__是这个函数对象的代码对象 code object

看看返回值,a 和2, 也就是第5列

那么第1列的2是什么?看起来好像很神秘的样子,其实不过是源代码中的行号。本例中表示是在double 代码的第2行。

 

上次详细解释过,b'|\x00\x00d\x01\x00\x14S' 其实是8个整数

 

 

>>> double.__code__.co_code
b'|\x00\x00d\x01\x00\x14S'
>>> for i in  double.__code__.co_code:
    print (i, end="    ")

    
124    0    0    100    1    0    20    83    

 

 

 

通过查字典或者另一个更加巧妙正常的办法,你可以找出124代表的opcode是 LOAD_FAST,  100代表 LOAD_CONST

这类opcode 后面各带两个字节的参数,分别是0  0   和 1  0 

但有些opcode后面是没有参数的,比如 83 代表的 RETURN_VALUE

        不了解的人可能会觉得有点奇怪,为什么RETURN_VALUE不带参数呢,不带参数怎么返回结果呢?

        查一查资料,RETURN_VALUE的意思是 Returns with TOS to the caller of the function. 即把TOS返回给这个函数的调用者。TOS= top of stack, 。咱出栈了。

 

现在问题来了:为什么要与字节码 bytecode 玩耍? 直接写Python代码方便多了,为什么要去写字节码?

 

因为可以节省编译时间,这里有一篇非常详细的文章,作者在遗传编程领域工作,发现他们Python 程序的总运算时间中,有50%都被编译过程吃掉。于是作者深入到 bytecode 层次进行了小小改动,大幅削减了编译时间,把总的运算时间降至不足原先的一半。

可惜没有找到这篇文章的中文翻译。不知道有没有人肯出钱让我翻译。

文中写道:

       bytecode 写好之后,我们必须让Python 明白它要执行这些bytecode。这时就需要创建一个完整的 code object。 

       bytecode 是 code object 的主要成分,但是还需要其他东西才能构成完整的 code object。就像鸡丁是宫保鸡丁中的主要食材,但它也不能没有花生。

       这个过程中要用到types.CodeType()

       有了code object 之后,接下来可以调用Types.FunctionType,利用这些代码创建一个函数对象( function object)。

 

上一篇写了怎么抽丝剥茧,顺着function object 找 code object,再找 bytecode,这里就完全倒过来,添枝加叶,逆流而上了。

 

转载于:https://www.cnblogs.com/hello2764/p/5466945.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值