引言
對iterator一般可以用for in方法處理,但有時可以藉助更高效、也更易讀的方式去處理。
例如解析式(包括列表解析式、生成器解析式、集合解析式、字典解析式),
例如map( )、reduce( )函式可以對iterator中的單個物件進行個別處理或迭代處理。
列表解析式
# 列表解析 [expr for item in iterator]
# 列表解析返回的是列表,內容是表示式執行的結果 # expr=variable print([x for x in range(10)]) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # expr=function def inc(x): return x+1 print([inc(x) for x in range(10)]) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # expr=expression print([(x+1)**2 for x in range(10)]) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# if判斷 [expr for item in iterator if cond] / [expr for item in iterator if cond1 if cond2] print([x for x in range(10) if x%2==0]) [0, 2, 4, 6, 8] print([x for x in range(10) if x%2==0 if x>4]) [6, 8] print([(x,y) for x in range(10) if x%2==0 for y in range(10) if y>=8]) [(0, 8), (0, 9), (2, 8), (2, 9), (4, 8), (4, 9), (6, 8), (6, 9), (8, 8), (8, 9)] # for x in iterator:
for y in iterator:
retrun (x,y) print([(x,y) for x in range(1,3) for y in range(0,2)]) [(1, 0), (1, 1), (2, 0), (2, 1)] # 列表解析用於對可迭代物件做過濾和轉換 print([(x+1,x+2) for x in range(5)]) [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] print([{x:x+1} for x in range(5)]) [{0: 1}, {1: 2}, {2: 3}, {3: 4}, {4: 5}]
生成器解析
# 生成器解析式按需計算的,又叫做延遲計算或惰性求值 def inc(x): return "inc {}".format(x) # 和列表解析不同的是,生成器解析的返回結果是一個generator,需要當成生成器去使用 print((inc(x) for x in range(10))) <generator object <genexpr> at 0x7f7ef2b0d9e8> print([inc(x) for x in range(3)]) ['inc 0', 'inc 1', 'inc 2'] g=(inc(x) for x in range(10)) print(next(g)) inc 0 print(next(g)) inc 1 # 生成式解析中各種if和for語句都一併適用 g=(inc(x) for x in range(10) if x%2==0 and x!=4) print(next(g)) inc 0 print(next(g)) inc 2 print(next(g)) inc 6
集合解析
# 集合解析的返回結果是集合 print({x for x in range(10) if x%2!=0}) {1, 3, 5, 9, 7} # 所以結果依舊會滿足集合的一切特性 print({x for x in [2,3,6,2,3,6]}) {2, 3, 6}
字典解析
# 字典解析也是使用大括號包圍,並且需要兩個表示式,一個生成key,一個生成value # 兩個表示式之間使用冒號分割,返回結果是字典 print({str(x):x for x in range(5)}) {'2': 2, '0': 0, '4': 4, '1': 1, '3': 3} print(type({str(x):x for x in range(5)})) <class 'dict'>
map()
# map(func, *iterables) --> map object
# map()函式接收兩個引數,一個是函式,一個是序列,map將傳入的函式依次作用到序列的每個元素 # python3中,直接map的返回值是map物件,如果想輸出可以list(map()) def f(x): return x*x print(map(f,[1,2,3,4,5])) <map object at 0x7ffe619a00f0> print(list(map(f,[1,2,3,4,5]))) [1, 4, 9, 16, 25] # func可以是任意複雜的函式 print(list(map(str,[1,2,3,4,5]))) ['1', '2', '3', '4', '5']
functools.reduce()
# reduce(function, sequence[, initial]) -> value
# reduce把一個函式作用在一個序列[x1, x2, x3...]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算 # 即reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
# python3中,reduce()已從全域性名字空間中移出了,被放置在fucntools模組裡 from functools import reduce def add(x,y): return x+y print(reduce(add,range(10))) 45 #把一個序列[1,3,5,7,9]變成int(13579) def fn(x,y): return x*10+y print(reduce(fn,[1,3,5,7,9])) 13579 print(type(reduce(fn,[1,3,5,7,9]))) <class 'int'>
# initial存在,可以在前面加上設定的string
import functools resourceConfigFiles=[ "server.properties.jinja2", "net.properties.jinja2", ] binConfigFiles = ['socket.jinja2'] jadeConfigFiles = ['ja.cfg.jinja2'] excludeproperties = functools.reduce( lambda x, y: '%s --exclude="%s"' %(x, y.rstrip('.jinja2')), resourceConfigFiles + jadeConfigFiles + binConfigFiles, "--test") print(excludeproperties) --test --exclude="server.properties" --exclude="net.properties" --exclude="ja.cfg" --exclude="socket"
一些map()和reduce()的小應用:
# 把str'13579'——>int(13579) def str2int(s): def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] def fn(x,y): return x*10+y return reduce(fn,map(char2num,s)) print(type(str2int('13579'))) <class 'int'> print(str2int('13579')) 13579
# 輸出規範的字串,首字母皆為大寫,其餘均為小寫 # ['adam','LISA','barT']——>['Adam','Lisa','Bart'] def cg_str(lst): return list(map(lambda x:x.lower().title(),lst)) #或者用切片實現 def cg_str(lst): return list(map(lambda x:x[0].upper()+x[1:].lower(),lst)) print(cg_str(['adam','LISA','barT'])) ['Adam', 'Lisa', 'Bart']
# 類似於sum(),實現一個階乘prod()函式 def prod(lst): return reduce(lambda x,y:x*y,lst) print(prod([1,2,3,4,5])) 120