關于Pythonic定義,參考文章:What does pythonic mean?
以下通過對比Bad way和Elegant way介紹一些常見的Pythonic寫法。
使用字典默認值
需求:在取dict的值的時候,假設某個key不存在,希望賦予其一個默認的值。
比較糟糕的方式:使用if去判斷key是否存在,不存在則給其賦予默認值。如下:
person = {
"name": "xiaohong",
"age": 12,
}
name = person['name'] if person.get('name') else "nobody"
優雅的寫法:
name = person.get("name", "nobody")
dict類型的get方法是可以設置缺省值的。
使用enumerate關鍵字
需求:對列表進行迭代的時候,需要同時訪問偏移量。
比較糟糕的方式:定義一個起始索引值,每迭代一次索引值計數一次。如下:
names = ["Zhang san", "Li si", "Wang wu"]
index = 0
for name in names:
print("The {0} is in position: {1}".format(name, index))
index += 1
或者
names = ["Zhang san", "Li si", "Wang wu"]
for position in range(0, len(names)):
print("The {0} is in position: {1}".format(names[position], position))
優雅的寫法:
names = ["Zhang san", "Li si", "Wang wu"]
for position, name in enumerate(names):
print("The {0} is in position: {1}".format(name, position))
用enumerate關鍵字進行迭代的過程中可同時返回索引以及值。
for else的巧用
需求:在一個列表中查找某個元素,如果,找到這個元素,立刻結束查找;如果未查找到則打印未找到。
比較糟糕的方式:定義一個變量用來標示是否找到。如下:
names = ["Zhang san", "Li si", "Wang wu"]
for name in names:
if name == 'Gou er dan':
found = True
break
if found is False:
print("未找到")
優雅的寫法:
names = ["Zhang san", "Li si", "Wang wu"]
found = False
for name in names:
if name == 'Gou er dan':
found = True
break
else:
print("未找到")
for else語句,如果for循環執行完畢,則會執行else語句塊,否則,不執行else語句塊。
with關鍵字的使用
需求:讀寫文件或者使用進程鎖。
比較糟糕的方式,手動管理文件的關閉或者打開。如:
f = open("test.txt", "r")
try:
text = f.read()
print(text)
finally:
f.close()
或者
import threading
lock = threading.Lock()
lock.acquire()
try:
print("Balabala")
finally:
lock.release()
優雅的寫法:
with open("test.txt", "r") as f:
print(f.read())
和
import threading
lock = threading.Lock()
with lock:
print("balabala")
使用with避免自己手動釋放資源。
同時遍歷二個列表
需求:同時遍歷二個列表。
比較糟糕的方式,定義下標去索引,如:
numbers = [1, 2, 3, 4]
english = ['one', 'two', 'three']
n = min(len(numbers), len(english))
for i in range(n):
print("{0} is {1}".format(numbers[i], english[i]))
優雅的寫法:
numbers = [1, 2, 3, 4]
english = ['one', 'two', 'three']
for number, name in zip(numbers, english):
print("{0} is {1}".format(number, name))
使用takewhile代替break
需求:在每次循環開始時,判斷循環是否需要提前結束。
不地道的寫法:使用break。如:
for user in users:
if not is_qualified(user):
break
地道的寫法:
from itertools import takewhile
for user in takewhile(is_qualified, users):
# ....
對于這類需要提前中斷的循環,我們可以使用 takewhile() 函數來簡化它。takewhile(predicate,iterable)會在迭代iterable的過程中不斷使用當前對象作為參數調用predicate函數并測試返回結果,如果函數返回值為真,則生成當前對象,循環繼續。否則立即中斷當前循環。
使用defaultdict
需求:統計一組字符串出現的頻率。
不優雅的寫法:
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
name_count = dict()
for name in names:
if not name_count.get(name):
name_count['name'] = 0
else:
name_count['name'] += 1
優雅的寫法:
from collections import defaultdict
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
name_count = defaultdict(int)
for name in names:
name_count[name] += 1
更加優雅的寫法:
from collections import Counter
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
print(Counter(names))
還有很多,下次接著寫...
并且,繼續更新中 ...