鏈?zhǔn)奖容^操作
>>> False == False == True
False
pythonic:
if 18 < age < 60:
print("yong man")
if/else 三目運(yùn)算
text = '男' if gender == 'male' else '女'
在類C的語言中都支持三目運(yùn)算 b?x:y
但在python能夠用 if/else 清晰表達(dá)邏輯時(shí)术奖,就沒必要再額外新增一種方式來實(shí)現(xiàn)俱箱。
真值判斷
檢查某個(gè)對(duì)象是否為真值時(shí)牙甫,還顯示地與 True 和 False 做比較就顯得多此一舉,不專業(yè)衰伯。
一般:
if attr == True:
do_something()
if len(values) != 0: # 判斷列表是否為空
do_something()
pythonic:
if attr:
do_something()
if values:
do_something()
for/else語句
for else 是 Python 中特有的語法格式,else 中的代碼在 for 循環(huán)遍歷完所有元素之后執(zhí)行。
一般:
flagfound = False
for i in mylist:
if i == theflag:
flagfound = True
break
process(i)
if not flagfound:
raise ValueError("List argument missing terminal flag.")
pythonic:
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("List argument missing terminal flag.")
字符串格式化
一般:
s1 = "foofish.net"
s2 = "vttalk"
s3 = "welcome to %s and following %s" % (s1, s2)
pythonic:
s3 = "welcome to {blog} and following {wechat}".format(blog="foofish.net", wechat="vttalk")
很難說用 format 比用 %s 的代碼量少,但是 format 更易于理解甘磨。
列表切片
獲取列表中的部分元素最先想到的就是用 for 循環(huán)根據(jù)條件提取元素,這也是其它語言中慣用的手段眯停,而在 Python 中還有強(qiáng)大的切片功能济舆。
一般:
items = range(10)
# 奇數(shù)
odd_items = []
for i in items:
if i % 2 != 0:
odd_items.append(i)
# 拷貝
copy_items = []
for i in items:
copy_items.append(i)
pythonic:
# 第1到第4個(gè)元素的范圍區(qū)間
sub_items = items[1:4]
# 奇數(shù)
odd_items = items[1::2]
#拷貝
copy_items = items[::] 或者 items[:]
列表元素的下標(biāo)不僅可以用正數(shù)表示,還是用負(fù)數(shù)表示莺债,最后一個(gè)元素的位置是 -1滋觉,從右往左,依次遞減齐邦。
--------------------------
| P | y | t | h | o | n |
--------------------------
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
--------------------------
善用生成器
一般:
def fib(n):
a, b = 0, 1
result = []
while b < n:
result.append(b)
a, b = b, a+b
return result
pythonic:
def fib(n):
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
上面是用生成器生成費(fèi)波那契數(shù)列椎侠。生成器的好處就是無需一次性把所有元素加載到內(nèi)存,只有迭代獲取元素時(shí)才返回該元素措拇,而列表是預(yù)先一次性把全部元素加載到了內(nèi)存我纪。此外用 yield 代碼看起來更清晰。
獲取字典元素
一般:
d = {'name': 'foo'}
if d.has_key('name'):
print(d['name'])
else:
print('unkonw')
pythonic:
d.get("name", "unknow")
預(yù)設(shè)字典默認(rèn)值
通過 key 分組的時(shí)候丐吓,不得不每次檢查 key 是否已經(jīng)存在于字典中浅悉。
一般:
data = [('foo', 10), ('bar', 20), ('foo', 39), ('bar', 49)]
groups = {}
for (key, value) in data:
if key in groups:
groups[key].append(value)
else:
groups[key] = [value]
pythonic:
# 第一種方式
groups = {}
for (key, value) in data:
groups.setdefault(key, []).append(value)
# 第二種方式
from collections import defaultdict
groups = defaultdict(list)
for (key, value) in data:
groups[key].append(value)
字典推導(dǎo)式
numbers = [1, 2, 3]
my_dict = {number: number * 2 for number in numbers}
print(my_dict) # {1: 2, 2: 4, 3: 6}
# 還可以指定過濾條件
my_dict = {number: number * 2 for number in numbers if number > 1}
print(my_dict) # {2: 4, 3: 6}
變量交換
一般:
>>> a = 1
>>> b = 2
>>> tmp = a
>>> a = b
>>> b = tmp
pythonic:
>>> a, b = b, a
帶有索引位置的集合遍歷
遍歷集合時(shí)如果需要使用到集合的索引位置時(shí),直接對(duì)集合迭代是沒有索引信息的券犁。
一般:
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
字符串連接
一般:
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 是一種更加高效的字符串連接方式术健,使用 + 操作時(shí),每執(zhí)行一次+操作就會(huì)導(dǎo)致在內(nèi)存中生成一個(gè)新的字符串對(duì)象族操,遍歷8次有8個(gè)字符串生成苛坚,造成無謂的內(nèi)存浪費(fèi)。而用 join 方法整個(gè)過程只會(huì)產(chǎn)生一個(gè)字符串對(duì)象色难。
打開/關(guān)閉文件
一般:
f = open('data.txt')
try:
data = f.read()
finally:
f.close()
pythonic:
with open('data.txt') as f:
data = f.read()
列表推導(dǎo)式
能夠用一行代碼簡(jiǎn)明扼要地解決問題時(shí)泼舱,絕不要用兩行
一般:
result = []
for i in range(10):
result.append(i)
pythonic:
[i for i in range(10)]
善用裝飾器
裝飾器可以把與業(yè)務(wù)邏輯無關(guān)的代碼抽離出來,讓代碼保持干凈清爽枷莉,而且裝飾器還能被多個(gè)地方重復(fù)利用娇昙。比如一個(gè)爬蟲網(wǎng)頁(yè)的函數(shù),如果該 URL 曾經(jīng)被爬過就直接從緩存中獲取笤妙,否則爬下來之后加入到緩存冒掌,防止后續(xù)重復(fù)爬取。
一般:
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.request as urllib
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()
用裝飾器寫代碼表面上感覺代碼量更多蹲盘,但是它把緩存相關(guān)的邏輯抽離出來了股毫,可以給更多的函數(shù)調(diào)用,這樣總的代碼量就會(huì)少很多召衔,而且業(yè)務(wù)方法看起來簡(jiǎn)潔了铃诬。
合理使用列表
列表對(duì)象(list)是一個(gè)查詢效率高于更新操作的數(shù)據(jù)結(jié)構(gòu),比如刪除一個(gè)元素和插入一個(gè)元素時(shí)執(zhí)行效率就非常低,因?yàn)檫€要對(duì)剩下的元素進(jìn)行移動(dòng)趣席。
一般:
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 是一個(gè)雙向隊(duì)列的數(shù)據(jù)結(jié)構(gòu)兵志,刪除元素和插入元素會(huì)很快
序列解包
一般:
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
遍歷字典的 key 和 value
方法一速度沒那么快,因?yàn)槊看蔚臅r(shí)候還要重新進(jìn)行hash查找 key 對(duì)應(yīng)的 value宣肚。
# 方法一
for k in d:
print k, '--->', d[k]
方法二遇到字典非常大的時(shí)候想罕,會(huì)導(dǎo)致內(nèi)存的消耗增加一倍以上。
# 方法二
for k, v in d.items():
print k, '--->', v
pythonic:
for k, v in d.iteritems():
print k, '--->', v
iteritems 返回迭代器對(duì)象霉涨,可節(jié)省更多的內(nèi)存按价,不過在 python3 中沒有該方法了,只有 items 方法嵌纲,等值于 iteritems俘枫。