目录

Python中的坑while1比whileTrue更快

目录

Python中的坑?while1比whileTrue更快?

1、前言

前些天被Python的多线程坑了一把,本篇讲的内容是Python的bool类型。

2、前提

2.1 bool是int的子类

根据PEP285中Review部分第6条所述,bool类是从int类继承而来的,这样可以极大的简化实现(C代码中调用PyInt_Check()的地方仍将继续工作)。

更多Python视频、源码、资料加群683380553免费获取

2.2 Python2中True/False不是关键字,但Python3中是

我们可以导入keyword模块,来查看关键字:

https://i-blog.csdnimg.cn/blog_migrate/08c734f69d6aa6e3e93a96f249a5613d.png

而在Python3中,关键字中添加了True/False/None。

由于Python2中True/False不是关键字,因此我们可以对其进行任意的赋值:

https://i-blog.csdnimg.cn/blog_migrate/6b01991809bca0bb216380f8239c39d8.png

3. True + True = 2

由于bool是继承自int的子类,因此为了保证向下兼容性,在进行算术运算中,True/False会被当作int值来执行。

https://i-blog.csdnimg.cn/blog_migrate/a978d0f9c248de0160b6435daf651757.png

4. While 1比While True快?

首先来看一个比较while 1和while True循环的脚本,两个函数中,除了1和True的区别之外,其他地方完全相同。

https://i-blog.csdnimg.cn/blog_migrate/6e810162419ec3e492a7662a2d721223.png

执行结果:

while one: 1.37000703812

while_true: 2.07638716698

可以看出wihle 1的执行时间约为while True的2/3。

那么,这是为什么呢?

其实这就是前提中提到的关键字的问题。由于Python2中,True/False不是关键字,因此我们可以对其进行任意的赋值,这就导致程序在每次循环时都需要对True/False的值进行检查;而对于1,则被程序进行了优化,而后不会再进行检查。

我们可以通过dis模块来查看while_one和while_true的字节码,下面的程序是对刚才的程序进行了一定的简化后的版本。

https://i-blog.csdnimg.cn/blog_migrate/43f51fea6a9dd9598d8972da5f972e0a.png

执行的结果是:

https://i-blog.csdnimg.cn/blog_migrate/e134177687e9e6f3f69afd1ce82a29c7.png

可以看出,正如上面所讲到的,在while True的时候,字节码中多出了几行语句,正是这几行语句进行了True值的检查。

而在Python3中,由于True/False已经是关键字了,不允许进行重新赋值,因此,其执行结果与while 1不再有区别(好吧,我这没有Python3的环境,就不去验证了,网上有人验证过了)。但是由于Python2的使用十分广泛,因此大家不得不注意这个可能会降低性能的地方。

5. if x == True: 还是 if x:

在PEP285中,还提到了这两种写法的比较。PEP285中认为,==具有传递性,a==b, b==c会被化简为a==c。也就是说,如果选择前一种写法的话,6和7在if语句中都应该被认为是真值,那么就会造成6==True==7,被化简为6==7的问题,因此后一种写法才是正确的。

现在,让我们偏个题,假设x就是True,那么程序的执行效率又如何呢?

https://i-blog.csdnimg.cn/blog_migrate/321e0853c72d1253e943b1a3c4b4756e.png

执行结果是:

if_x_eq_true: 0.212558031082

if_x: 0.144327878952

让我们再来看看字节码(程序未作修改,dis的使用方式同上,因此不再给出程序):

https://i-blog.csdnimg.cn/blog_migrate/7f9c75d338fe5bdc0a40ff95189ddef6.png

可以清晰的看到第9行比第14行,多出了检查True值和进行比较的操作。

也就是说,不论从遵循PEP的规范,还是执行效率,或者程序的简洁性来说,我们都应该使用if x:,而不是if x == True:来进行比较。同理,那些if x is not None:之类的语句也应当被简化为if x:(如果要比较的是非值,而不必须是None的话)。

https://i-blog.csdnimg.cn/blog_migrate/6a7b11e7b1be0b3b7bedec36a70c9deb.png