當前位置:
首頁 > 知識 > 代碼這樣寫更優雅(Python 版)

代碼這樣寫更優雅(Python 版)

(點擊

上方藍字

,快速關注我們)




來源:伯樂在線/劉志軍 ,微信公號:Python之禪(ID:VTtalk)


foofish.net/idiomatic_python.html


如有好文章投稿,請點擊 → 這裡了解詳情




Python 這門語言最大的優點之一就是語法簡潔,好的代碼就像偽代碼一樣,乾淨、整潔、一目了然。但有時候我們寫代碼,特別是 Python 初學者,往往還是按照其它語言的思維習慣來寫,那樣的寫法不僅運行速度慢,代碼讀起來也費盡,給人一種拖泥帶水的感覺,過段時間連自己也讀不懂。



《計算機程序的構造和解釋》的作者哈爾·阿伯爾森曾這樣說:「Programs must be written for people to read, and only incidentally for machines to execute.」




要寫出 Pythonic(優雅的、地道的、整潔的)代碼,還要平時多觀察那些大牛代碼,Github 上有很多非常優秀的源代碼值得閱讀,比如:requests、flask、tornado,筆者列舉一些常見的 Pythonic 寫法,希望能給你帶來一點啟迪。




1、變數交換




大部分編程語言中交換兩個變數的值時,不得不引入一個臨時變數:





>>>

a

=

1


>>>

b

=

2


>>>

tmp

=

a


>>>

a

=

b


>>>

b

=

tmp



pythonic





>>> a, b = b, a




2、循環遍歷區間元素




for

i

in

[

0

,

1

,

2

,

3

,

4

,

5

]

:


(

print

i

)


# 或者


for

i

in

range

(

6

)

:


(

print

i

)




pythonic





for

i

in

xrange

(

6

)

:


(

print

i

)




xrange 返回的是生成器對象,生成器比列表更加節省內存,不過需要注意的是 xrange 是 python2 中的寫法,python3 只有 range 方法,特點和 xrange 是一樣的。




3、帶有索引位置的集合遍歷




遍歷集合時如果需要使用到集合的索引位置時,直接對集合迭代是沒有索引信息的,普通的方式使用:





colors

=

[

"red"

,

"green"

,

"blue"

,

"yellow"

]



for

i

in

range

(

len

(

colors

))

:


print

(

i

,

"--->"

,

colors

[

i

])




pythonic





for

i

,

color

in

enumerate

(

colors

)

:


print

(

i

,

"--->"

,

color

)




4、字元串連接




字元串連接時,普通的方式可以用 + 操作





names

=

[

"raymond"

,

"rachel"

,

"matthew"

,

"roger"

,


"betty"

,

"melissa"

,

"judith"

,

"charlie"

]



s

=

names

[

0

]


for

name

in

names

[

1

:

]

:


s

+=

", "

+

name


print

(

s

)




pythonic





print (", ".join(names))




join 是一種更加高效的字元串連接方式,使用 + 操作時,每執行一次+操作就會導致在內存中生成一個新的字元串對象,遍歷8次有8個字元串生成,造成無謂的內存浪費。而用 join 方法整個過程只會產生一個字元串對象。




5、打開/關閉文件




執行文件操作時,最後一定不能忘記的操作是關閉文件,即使報錯了也要 close。普通的方式是在 finnally 塊中顯示的調用 close 方法。





f

=

open

(

"data.txt"

)


try

:


data

=

f

.

read

()


finally

:


f

.

close

()




pythonic





with

open

(

"data.txt"

)

as

f

:


data

=

f

.

read

()




使用 with 語句,系統會在執行完文件操作後自動關閉文件對象。




6、列表推導式




能夠用一行代碼簡明扼要地解決問題時,絕不要用兩行,比如





result

=

[]


for

i

in

range

(

10

)

:


s

=

i

*

2


result

.

append

(

s

)




pythonic





[i*2 for i in xrange(10)]




與之類似的還有生成器表達式、字典推導式,都是很 pythonic 的寫法。




7、善用裝飾器




裝飾器可以把與業務邏輯無關的代碼抽離出來,讓代碼保持乾淨清爽,而且裝飾器還能被多個地方重複利用。比如一個爬蟲網頁的函數,如果該 URL 曾經被爬過就直接從緩存中獲取,否則爬下來之後加入到緩存,防止後續重複爬取。





def

web_lookup

(

url

,

saved

=

{})

:


if

url

in

saved

:


return

saved

[

url

]


page

=

urllib

.

urlopen

(

url

).

read

()


saved

[

url

]

=

page


return

page




pythonic





import

urllib

#py2


#import urllib.request as urllib # py3



def

cache

(

func

)

:


saved

=

{}



def

wrapper

(

url

)

:


if

url

in

saved

:


return

saved

[

url

]


else

:


page

=

func

(

url

)


saved

[

url

]

=

page


return

page



return

wrapper



def

web_lookup

(

url

)

:


return

urllib

.

urlopen

(

url

).

read

()




用裝飾器寫代碼表面上感覺代碼量更多,但是它把緩存相關的邏輯抽離出來了,可以給更多的函數調用,這樣總的代碼量就會少很多,而且業務方法看起來簡潔了。




8、合理使用列表




列表對象(list)是一個查詢效率高於更新操作的數據結構,比如刪除一個元素和插入一個元素時執行效率就非常低,因為還要對剩下的元素進行移動





names

=

[

"raymond"

,

"rachel"

,

"matthew"

,

"roger"

,


"betty"

,

"melissa"

,

"judith"

,

"charlie"

]


names

.

pop

(

0

)


names

.

insert

(

0

,

"mark"

)




pythonic





from

collections

import

deque


names

=

deque

([

"raymond"

,

"rachel"

,

"matthew"

,

"roger"

,


"betty"

,

"melissa"

,

"judith"

,

"charlie"

])


names

.

popleft

()


names

.

appendleft

(

"mark"

)




deque 是一個雙向隊列的數據結構,刪除元素和插入元素會很快




9、序列解包





p

=

"vttalk"

,

"female"

,

30

,

"python@qq.com"



name

=

p

[

0

]


gender

=

p

[

1

]


age

=

p

[

2

]


email

=

p

[

3

]




pythonic





name, gender, age, email = p




10、遍歷字典的 key 和 value




方法一速度沒那麼快,因為每次迭代的時候還要重新進行hash查找 key 對應的 value。




方法二遇到字典非常大的時候,會導致內存的消耗增加一倍以上





# 方法一


for

k

in

d

:


print

(

k

,

"--->"

,

d

[

k

])



# 方法二


for

k

,

v

in

d

.

items

()

:


print

(

k

,

"--->"

,

v

)




pythonic





for

k

,

v

in

d

.

iteritems

()

:


print

(

k

,

"--->"

,

v

)




iteritems 返回迭代器對象,可節省更多的內存,不過在 python3 中沒有該方法了,只有 items 方法,等值於 iteritems。




當然還有很多 pythonic 寫法,在此不再一一列舉,說不定有第二期,歡迎留言。覺得不錯就zan一個吧 (^o^)/




看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

Python——正則表達式基礎知識的簡介
關於 Python 多線程的一些思考
免費直播教你如何零基礎入門Python Web?
Python 菜鳥教程

TAG:Python |

您可能感興趣

Google出品的Python代碼靜態類型分析器:Pytype
利用你所知道的Python技巧寫出更加Pythonic的代碼
人臉識別的簡單介紹(含Python代碼)
PyTorch代碼調試利器:自動print每行代碼的Tensor信息
這5小段代碼輕鬆實現數據可視化(Python+Matplotlib)
Numba和Cython如何加速Python代碼
SyncRequestProcessor 小代碼 大優雅
Canonical:可在Ubuntu軟體庫獲取Intel的最新微代碼補丁
windows、Linux與OS X相比,哪個系統更適合寫代碼?
【代碼分享】系列之樸素貝葉斯(github clone)
趣圖:用 Python 重構 PHP 代碼
Github 代碼實踐:Pytorch 實現的語義分割器
Github代碼實踐:Pytorch實現的語義分割器
Wandb用起來,一行Python代碼實現Keras模型可視化
學慣用 Thonny 寫代碼:一個面向初學者的Python IDE
給數據科學家的 Python 3 指導;簡單 chatbot 代碼實現
DeBug Python代碼全靠print函數?換用這個一天2K+Star的工具吧
利用PHPstorm進行代碼review
iOS 代碼使用 C+的zero-cost abstraction 特性
破譯代碼 Ryzen版Chromebook被曝光