Python 這門語言最大的優勢之一就是語法簡潔,好的代碼就像僞代碼同樣,乾淨、整潔、一目瞭然。但有時候咱們寫代碼,特別是 Python 初學者,每每仍是按照其它語言的思惟習慣來寫,那樣的寫法不只運行速度慢,代碼讀起來也費盡,給人一種拖泥帶水的感受,過段時間連本身也讀不懂。html
《計算機程序的構造和解釋》的做者哈爾·阿伯爾森曾這樣說:「Programs must be written for people to read, and only incidentally for machines to execute.」 python
要寫出 Pythonic(優雅的、地道的、整潔的)代碼,還要平時多觀察那些大牛代碼,Github 上有不少很是優秀的源代碼值得閱讀,好比:requests、flask、tornado,筆者列舉一些常見的 Pythonic 寫法,但願能給你帶來一點啓迪。程序員
大部分編程語言中交換兩個變量的值時,不得不引入一個臨時變量:web
>>> a = 1
>>> b = 2
>>> tmp = a
>>> a = b
>>> b = tmp複製代碼
pythonic編程
>>> a, b = b, a複製代碼
for i in [0, 1, 2, 3, 4, 5]:
print i2
# 或者
for i in range(6):
print i2複製代碼
pythonicflask
for i in xrange(6):
print i2複製代碼
xrange 返回的是生成器對象,生成器比列表更加節省內存,不過須要注意的是 xrange 是 python2 中的寫法,python3 只有 range 方法,特色和 xrange 是同樣的。緩存
遍歷集合時若是須要使用到集合的索引位置時,直接對集合迭代是沒有索引信息的,普通的方式使用:數據結構
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print i, '--->', colors[i]複製代碼
pythonicapp
for i, color in enumerate(colors):
print i, '--->', color複製代碼
字符串鏈接時,普通的方式能夠用 +
操做編程語言
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 方法整個過程只會產生一個字符串對象。
執行文件操做時,最後必定不能忘記的操做是關閉文件,即便報錯了也要 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 語句,系統會在執行完文件操做後自動關閉文件對象。
可以用一行代碼簡明扼要地解決問題時,毫不要用兩行,好比
result = []
for i in range(10):
s = i 2
result.append(s)複製代碼
pythonic
[i2 for i in xrange(10)]複製代碼
與之相似的還有生成器表達式、字典推導式,都是很 pythonic 的寫法。
裝飾器能夠把與業務邏輯無關的代碼抽離出來,讓代碼保持乾淨清爽,並且裝飾器還能被多個地方重複利用。好比一個爬蟲網頁的函數,若是該 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
@cache
def web_lookup(url):
return urllib.urlopen(url).read()複製代碼
用裝飾器寫代碼表面上感受代碼量更多,可是它把緩存相關的邏輯抽離出來了,能夠給更多的函數調用,這樣總的代碼量就會少不少,並且業務方法看起來簡潔了。
列表對象(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 是一個雙向隊列的數據結構,刪除元素和插入元素會很快
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複製代碼
方法一速度沒那麼快,由於每次迭代的時候還要從新進行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 寫法,在此再也不一一列舉,說不定有第二期,歡迎留言。以爲不錯就贊一個吧 (^o^)/
公衆號『一個程序員的微站』(id:VTtalk),分享 Python 等技術乾貨和有溫度的內容,歡迎關注
博客地址:foofish.net/idiomatic_p…