1. 程式人生 > >Python中的坑?while1比whileTrue更快?

Python中的坑?while1比whileTrue更快?

1、前言

前些天被Python的多執行緒坑了一把,本篇講的內容是Python的bool型別。

2、前提

2.1 bool是int的子類

根據PEP285中Review部分第6條所述,bool類是從int類繼承而來的,這樣可以極大的簡化實現(C程式碼中呼叫PyInt_Check()的地方仍將繼續工作)。

更多Python視訊、原始碼、資料加群960410445免費獲取

2.2 Python2中True/False不是關鍵字,但Python3中是

我們可以匯入keyword模組,來檢視關鍵字:

Python中的坑?while1比whileTrue更快?

 

而在Python3中,關鍵字中添加了True/False/None。

由於Python2中True/False不是關鍵字,因此我們可以對其進行任意的賦值:

Python中的坑?while1比whileTrue更快?

 

3. True + True = 2

由於bool是繼承自int的子類,因此為了保證向下相容性,在進行算術運算中,True/False會被當作int值來執行。

Python中的坑?while1比whileTrue更快?

 

4. While 1比While True快?

首先來看一個比較while 1和while True迴圈的指令碼,兩個函式中,除了1和True的區別之外,其他地方完全相同。

Python中的坑?while1比whileTrue更快?

 

執行結果:

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的位元組碼,下面的程式是對剛才的程式進行了一定的簡化後的版本。

Python中的坑?while1比whileTrue更快?

 

執行的結果是:

Python中的坑?while1比whileTrue更快?

 

可以看出,正如上面所講到的,在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,那麼程式的執行效率又如何呢?

Python中的坑?while1比whileTrue更快?

 

執行結果是:

if_x_eq_true: 0.212558031082

if_x: 0.144327878952

讓我們再來看看位元組碼(程式未作修改,dis的使用方式同上,因此不再給出程式):

Python中的坑?while1比whileTrue更快?

 

可以清晰的看到第9行比第14行,多出了檢查True值和進行比較的操作。

也就是說,不論從遵循PEP的規範,還是執行效率,或者程式的簡潔性來說,我們都應該使用if x:,而不是if x == True:來進行比較。同理,那些if x is not None:之類的語句也應當被簡化為if x:(如果要比較的是非值,而不必須是None的話)。

Python中的坑?while1比whileTrue更快?