代碼這樣寫更優雅(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
]
:
(
i
)
# 或者
for
i
in
range
(
6
)
:
(
i
)
pythonic
for
i
in
xrange
(
6
)
:
(
i
)
xrange 返回的是生成器對象,生成器比列表更加節省內存,不過需要注意的是 xrange 是 python2 中的寫法,python3 只有 range 方法,特點和 xrange 是一樣的。
3、帶有索引位置的集合遍歷
遍歷集合時如果需要使用到集合的索引位置時,直接對集合迭代是沒有索引信息的,普通的方式使用:
colors
=
[
"red"
,
"green"
,
"blue"
,
"yellow"
]
for
i
in
range
(
len
(
colors
))
:
(
i
,
"--->"
,
colors
[
i
])
pythonic
for
i
,
color
in
enumerate
(
colors
)
:
(
i
,
"--->"
,
color
)
4、字元串連接
字元串連接時,普通的方式可以用 + 操作
names
=
[
"raymond"
,
"rachel"
,
"matthew"
,
"roger"
,
"betty"
,
"melissa"
,
"judith"
,
"charlie"
]
s
=
names
[
0
]
for
name
in
names
[
1
:
]
:
s
+=
", "
+
name
(
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
]
=
p
[
3
]
pythonic
name, gender, age, email = p
10、遍歷字典的 key 和 value
方法一速度沒那麼快,因為每次迭代的時候還要重新進行hash查找 key 對應的 value。
方法二遇到字典非常大的時候,會導致內存的消耗增加一倍以上
# 方法一
for
k
in
d
:
(
k
,
"--->"
,
d
[
k
])
# 方法二
for
k
,
v
in
d
.
items
()
:
(
k
,
"--->"
,
v
)
pythonic
for
k
,
v
in
d
.
iteritems
()
:
(
k
,
"--->"
,
v
)
iteritems 返回迭代器對象,可節省更多的內存,不過在 python3 中沒有該方法了,只有 items 方法,等值於 iteritems。
當然還有很多 pythonic 寫法,在此不再一一列舉,說不定有第二期,歡迎留言。覺得不錯就zan一個吧 (^o^)/
看完本文有收穫?請轉
發分享給更多人
關注「P
ython開發者」,提升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被曝光