日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python while-Python天坑系列(一):while 1比while True更快?

發布時間:2024/1/23 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python while-Python天坑系列(一):while 1比while True更快? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

更多

0. 前言

前些天被Python的多線程坑了一把,因此產生了寫一個《Python天坑系列》博客的想法,說說我碰到的那些Python的坑。

而天坑這個詞呢,一方面指Python的坑,另一方面也說明本系列文章也是個坑,對于會寫什么內容、有多少篇、多久更新一次、什么時間更新我都無法確定,哈哈(看,之前已經3個月沒有更新過了!)。

本篇是系列的第一篇,講的內容是Python的bool類型。

1. 前提

1.1 bool是int的子類

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

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

我們可以導入keyword模塊,來查看關鍵字:

keyword

Python

# Python2 關鍵字

>>> import keyword

>>> keyword.kwlist

>>> ["and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "not", "or", "pass", "print", "raise", "return", "try", "while", "with", "yield"]

1

2

3

4

5

# Python2 關鍵字

>>>importkeyword

>>>keyword.kwlist

>>>["and","as","assert","break","class","continue","def","del","elif","else","except","exec","finally","for","from","global","if","import","in","is","lambda","not","or","pass","print","raise","return","try","while","with","yield"]

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

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

Python2 True賦值

Python

>>> (1 == 1) == True

True

>>> True = "pythoner.com"

>>> (1 == 1) == True

False

1

2

3

4

5

>>>(1==1)==True

True

>>>True="pythoner.com"

>>>(1==1)==True

False

2. True + True = 2

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

True + True = 2

Python

>>> True + True

2

>>> True - True

0

>>> True * True

1

>>> (True + True) > 1

True

>>> True + 5

6

>>> 1 / False

Traceback (most recent call last):

File "", line 1, in

ZeroDivisionError: integer division or modulo by zero

1

2

3

4

5

6

7

8

9

10

11

12

13

14

>>>True+True

2

>>>True-True

0

>>>True*True

1

>>>(True+True)>1

True

>>>True+5

6

>>>1/False

Traceback(mostrecentcalllast):

File"",line1,in

ZeroDivisionError:integerdivisionormodulobyzero

3. While 1比While True快?

首先來看一個比較while 1和while True循環的腳本,兩個函數中,除了1和True的區別之外,其他地方完全相同。

while 1與while True比較

Python

#! /usr/bin/python

# -*- coding: utf-8 -*-

import timeit

def while_one():

i = 0

while 1:

i += 1

if i == 10000000:

break

def while_true():

i = 0

while True:

i += 1

if i == 10000000:

break

if __name__ == "__main__":

w1 = timeit.timeit(while_one, "from __main__ import while_one", number=3)

wt = timeit.timeit(while_true, "from __main__ import while_true", number=3)

print "while one: %s while_true: %s" % (w1, wt)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#! /usr/bin/python

# -*- coding: utf-8 -*-

importtimeit

defwhile_one():

i=0

while1:

i+=1

ifi==10000000:

break

defwhile_true():

i=0

whileTrue:

i+=1

ifi==10000000:

break

if__name__=="__main__":

w1=timeit.timeit(while_one,"from __main__ import while_one",number=3)

wt=timeit.timeit(while_true,"from __main__ import while_true",number=3)

print"while one: %s while_true: %s"%(w1,wt)

執行結果:

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的字節碼,下面的程序是對剛才的程序進行了一定的簡化后的版本。

while 1和while True的字節碼程序

Python

#! /usr/bin/python

# -*- coding: utf-8 -*-

import dis

def while_one():

while 1:

pass

def while_true():

while True:

pass

if __name__ == "__main__":

print "while_one "

dis.dis(while_one)

print "while_true "

dis.dis(while_true)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#! /usr/bin/python

# -*- coding: utf-8 -*-

importdis

defwhile_one():

while1:

pass

defwhile_true():

whileTrue:

pass

if__name__=="__main__":

print"while_one "

dis.dis(while_one)

print"while_true "

dis.dis(while_true)

執行的結果是:

while 1和while True的字節碼執行結果

Python

while_one

6 0 SETUP_LOOP 3 (to 6)

7 >> 3 JUMP_ABSOLUTE 3

>> 6 LOAD_CONST 0 (None)

9 RETURN_VALUE

while_true

10 0 SETUP_LOOP 10 (to 13)

>> 3 LOAD_GLOBAL 0 (True)

6 POP_JUMP_IF_FALSE 12

11 9 JUMP_ABSOLUTE 3

>> 12 POP_BLOCK

>> 13 LOAD_CONST 0 (None)

16 RETURN_VALUE

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

while_one

60SETUP_LOOP3(to6)

7>>3JUMP_ABSOLUTE3

>>6LOAD_CONST0(None)

9RETURN_VALUE

while_true

100SETUP_LOOP10(to13)

>>3LOAD_GLOBAL0(True)

6POP_JUMP_IF_FALSE12

119JUMP_ABSOLUTE3

>>12POP_BLOCK

>>13LOAD_CONST0(None)

16RETURN_VALUE

可以看出,正如上面所講到的,在while True的時候,字節碼中多出了幾行語句,正是這幾行語句進行了True值的檢查。

而在Python3中,由于True/False已經是關鍵字了,不允許進行重新賦值,因此,其執行結果與while 1不再有區別(好吧,我這沒有Python3的環境,就不去驗證了,網上有人驗證過了)。但是由于Python2的使用十分廣泛,因此大家不得不注意這個可能會降低性能的地方。

4. if x == True: 還是 if x:

在PEP285中,還提到了這兩種寫法的比較。PEP285中認為,==具有傳遞性,a==b, b==c會被化簡為a==c。也就是說,如果選擇前一種寫法的話,6和7在if語句中都應該被認為是真值,那么就會造成6==True==7,被化簡為6==7的問題,因此后一種寫法才是正確的。

現在,讓我們偏個題,假設x就是True,那么程序的執行效率又如何呢?

if x == True:和if x:比較

Python

#! /usr/bin/python

# -*- coding: utf-8 -*-

import timeit

def if_x_eq_true():

x = True

if x == True:

pass

def if_x():

x = True

if x:

pass

if __name__ == "__main__":

if1 = timeit.timeit(if_x_eq_true, "from __main__ import if_x_eq_true", number = 1000000)

if2 = timeit.timeit(if_x, "from __main__ import if_x", number = 1000000)

print "if_x_eq_true: %s if_x: %s" % (if1, if2)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#! /usr/bin/python

# -*- coding: utf-8 -*-

importtimeit

defif_x_eq_true():

x=True

ifx==True:

pass

defif_x():

x=True

ifx:

pass

if__name__=="__main__":

if1=timeit.timeit(if_x_eq_true,"from __main__ import if_x_eq_true",number=1000000)

if2=timeit.timeit(if_x,"from __main__ import if_x",number=1000000)

print"if_x_eq_true: %s if_x: %s"%(if1,if2)

執行結果是:

if_x_eq_true: 0.212558031082

if_x: 0.144327878952

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

if x == True:和if x:的字節碼

Python

if_x_eq_true

8 0 LOAD_GLOBAL 0 (True)

3 STORE_FAST 0 (x)

9 6 LOAD_FAST 0 (x)

9 LOAD_GLOBAL 0 (True)

12 COMPARE_OP 2 (==)

15 POP_JUMP_IF_FALSE 21

10 18 JUMP_FORWARD 0 (to 21)

>> 21 LOAD_CONST 0 (None)

24 RETURN_VALUE

if_x

13 0 LOAD_GLOBAL 0 (True)

3 STORE_FAST 0 (x)

14 6 LOAD_FAST 0 (x)

9 POP_JUMP_IF_FALSE 15

15 12 JUMP_FORWARD 0 (to 15)

>> 15 LOAD_CONST 0 (None)

18 RETURN_VALUE

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

if_x_eq_true

80LOAD_GLOBAL0(True)

3STORE_FAST0(x)

96LOAD_FAST0(x)

9LOAD_GLOBAL0(True)

12COMPARE_OP2(==)

15POP_JUMP_IF_FALSE21

1018JUMP_FORWARD0(to21)

>>21LOAD_CONST0(None)

24RETURN_VALUE

if_x

130LOAD_GLOBAL0(True)

3STORE_FAST0(x)

146LOAD_FAST0(x)

9POP_JUMP_IF_FALSE15

1512JUMP_FORWARD0(to15)

>>15LOAD_CONST0(None)

18RETURN_VALUE

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

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

5. References

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的python while-Python天坑系列(一):while 1比while True更快?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。