Python 裏有個小彩蛋:python
在 Python Shell 裏輸入 import this
程序員
這段話被稱做「Python 之禪」(The Zen of Python),它列舉了一些 Python 所推崇的理念,好比:編程
優美勝於醜陋
明確勝於隱晦
簡單勝於複雜
…
可讀性很重要
不要忽略錯誤
面對不肯定時, 拒絕猜想
如今作好過不作,但盲目動手不如不作
若是你的實現很難說清楚,那是個壞想法;反之亦然
…
當你學完基礎,能夠寫點代碼的時候,可能常常感受本身的實現很彆扭。有經驗的程序員會一眼看出你的代碼出自一個初學者之手。這就是咱們常常說的,代碼不夠 pythonic。app
所謂 pythonic,我以爲包含兩方面:一是代碼的風格符合 Python 的特色,能合理使用 Python 的「語法糖」;二是代碼簡潔優美,穩定性高,可讀性好,便於維護和修改。所謂「Python 之禪」並不只限於 Python,不少理念是編程普適的。函數
好比來實現對一個列表中元素的遍歷訪問,我見過不少次有人這麼寫:學習
for i in range(len(lst)):
print(lst[i])
複製代碼
這樣的同窗極可能是以前有過 C/C++ 或 Java 的經驗。這麼寫功能上沒問題,但不夠簡潔,不夠 pythonic。更好的實現方式:this
for i in lst:
print(i)
複製代碼
這種不影響功能,但能簡化程序、提升可讀性的語法,咱們稱之爲「語法糖」(Syntactic sugar)。Python 中相似的例子還有很多,來舉幾個:spa
一、交換兩個變量的值,普通寫法:翻譯
temp = a
a = b
b = temp
複製代碼
pythonic 寫法:設計
a, b = b, a
複製代碼
二、相似的解包(unpacking)用法還能夠實現多個返回值的函數。普通寫法:
def func(a, b):
result = [b, a]
return result
r = func(a, b)
x = r[0]
y = r[1]
複製代碼
pythonic 寫法:
def func(a, b):
return b, a
x, y = func(a, b)
複製代碼
三、讀寫文件,普通寫法:
f = open('filename.txt')
text = f.read()
print(text)
f.close()
複製代碼
pythonic 寫法:
with open('filename.txt') as f:
for line in f:
print(line)
複製代碼
with
的好處是即便出錯,也會幫你關閉文件。
四、拼接字符串,普通寫法:
letters = ['h', 'e', 'l', 'l', 'o']
s = ''
for l in letters:
s += l
print(s)
複製代碼
pythonic 寫法:
print(''.join(letters))
複製代碼
五、關於前面遍歷列表的例子,若是你想帶上索引,能夠這麼寫:
for i, elem in enumerate(lst):
print(i, elem)
複製代碼
遍歷字典項:
for key, value in dct.items():
print(key, value)
複製代碼
六、取出列表中大於 0 的元素,生成新列表。普通寫法:
new_lst = []
for i in lst:
if i > 0:
new_lst.append(i)
複製代碼
pythonic 寫法:
new_lst = [i for i in lst if i > 0]
複製代碼
這個被稱爲「列表解析式」(List comprehension,中文翻譯說法有不少),能夠說是很是 pythonic 的一個用法了。
更進一步,若是數據量很大,而你對新列表僅僅是遍歷操做,並不須要一個列表對象,能夠採用生成器:
new_lst = (i for i in lst if i > 0)
for i in new_lst:
print(i)
複製代碼
這樣會更節省資源,提高執行效率。
七、判斷一個值是否爲True、是否爲空列表、是不是None,普通寫法:
if x == True:
pass
if len(y) == 0:
pass
if z == None:
pass
複製代碼
pythonic 寫法:
if x:
pass
if not y:
pass
if z is None:
pass
複製代碼
八、根據鍵名獲取字典中對應的值,普通寫法:
value = dct[key]
複製代碼
這樣的問題在於,若是 key
不存在,代碼就報錯跳出。因而你不得不增長更多的判斷。
pythonic 寫法:
value = dct.get(key, 0)
複製代碼
改用 get
方法,不存在時會獲得 None,或者指定的默認值(這裏是 0)。
篇幅所限,以上僅僅是一些比較具備表明性的例子。但凡事要有度,過度追求 pythonic 的寫法也可能致使代碼的可讀性降低。好比有人喜歡把不少功能寫在一個語句中,這反倒不 pythonic 了。因此,咱們須要有一些設計的原則,但又沒必要拘泥於具體的形式,不然就鑽入牛角尖了。
那麼對於學習者來講,如何才能寫出更 pythonic 的代碼呢?說到底仍是個經驗積累的過程,菜鳥不可能看本書、上個課就一晚上變成老鳥,但只要堅持得夠久就能夠。我這邊給幾個建議:
list(set(x))
這種用法。另外,對於代碼自己,Python 有一套書寫規範,叫作 PEP8。裏面約定了不少細節,好比哪裏該空格、註釋怎麼寫、什麼地方該換行、如何命名等等。連接:https://www.python.org/dev/peps/pep-0008/,網上還有翻譯好的中文版,務必找時間看一看。
最後,留2個小做業:
1. 判斷 一個列表 A 是否爲另外一個列表 B 的「子集」,也就是列表 A 中的元素是否都在列表 B 中。
2. 計算 1 加到 100 的和。
儘量寫出你認爲 pythonic 的代碼。
════
其餘文章及回答:
學編程:如何自學Python | 新手引導 | 一圖學Python
歡迎搜索及關注:Crossin的編程教室