遞歸函數:函數內部調用自身自己python
def fact(n): if n==1: return 1 return n * fact(n - 1)
使用遞歸函數的優勢是邏輯簡單清晰,缺點是過深的調用會致使棧溢出。
git
尾遞歸優化:設計模式
def fact(n): return fact_iter(n, 1) def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product)
能夠看到,return fact_iter(num - 1, num * product)
僅返回遞歸函數自己,num - 1
和num * product
在函數調用前就會被計算,不影響函數調用。閉包
fact(5)
對應的fact_iter(5, 1)
的調用以下:函數
===> fact_iter(5, 1) ===> fact_iter(4, 5) ===> fact_iter(3, 20) ===> fact_iter(2, 60) ===> fact_iter(1, 120) ===> 120
python的高級特性工具
1)切片優化
L[0:9:2]前10個數,每兩個取一個spa
2)迭代.net
for ... in
設計
由於dict的存儲不是按照list的方式順序排列,因此,迭代出的結果順序極可能不同。
字典的迭代
默認狀況下,dict迭代的是key。若是要迭代value,能夠用for value in d.values()
,若是要同時迭代key和value,能夠用for k, v in d.items()
。
因爲字符串也是可迭代對象,所以,也能夠做用於for
循環:
>>> for ch in 'ABC': ... print(ch) ... A B C
因此,當咱們使用for
循環時,只要做用於一個可迭代對象,for
循環就能夠正常運行,而咱們不太關心該對象到底是list仍是其餘數據類型。
3)列表生成式
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.items()] ['y=B', 'x=A', 'z=C']
運用列表生成式,能夠快速生成list,能夠經過一個list推導出另外一個list,而代碼卻十分簡潔
生成器:
generator是很是強大的工具,在Python中,能夠簡單地把列表生成式改爲generator,也能夠經過函數實現複雜邏輯的generator。
要理解generator的工做原理,它是在for
循環的過程當中不斷計算出下一個元素,並在適當的條件結束for
循環。對於函數改爲的generator來講,遇到return
語句或者執行到函數體最後一行語句,就是結束generator的指令,for
循環隨之結束。
請注意區分普通函數和generator函數,普通函數調用直接返回結果:
>>> r = abs(6) >>> r 6
generator函數的「調用」實際返回一個generator對象:
>>> g = fib(6)
>>> g
<generator object fib at 0x1022ef948>
定義生成器:generator function
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
生成式和生成器的區別
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>
迭代器:
直接做用於for
循環的對象統稱爲可迭代對象:Iterable
。
生成器不但能夠做用於for
循環,還能夠被next()
函數不斷調用並返回下一個值,直到最後拋出StopIteration
錯誤表示沒法繼續返回下一個值了。 能夠被next()
函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator
凡是可做用於for
循環的對象都是Iterable
類型;
凡是可做用於next()
函數的對象都是Iterator
類型,它們表示一個惰性計算的序列;
集合數據類型如list
、dict
、str
等是Iterable
但不是Iterator
,不過能夠經過iter()
函數得到一個Iterator
對象。
高階函數:
map()
函數接收兩個參數,一個是函數,一個是Iterable
,map
將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator
返回。
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
reduce
把一個函數做用在一個序列[x1, x2, x3, ...]
上,這個函數必須接收兩個參數,reduce
把結果繼續和序列的下一個元素作累積計算
>>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> def char2num(s): ... digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} ... return digits[s] ... >>> reduce(fn, map(char2num, '13579')
用lambda函數進一步簡化成:
from functools import reduce DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9} def char2num(s): return DIGITS[s] def str2int(s): return reduce(lambda x, y: x * 10 + y, map(char2num, s))
filter函數:
和map()
相似,filter()
也接收一個函數和一個序列。和map()
不一樣的是,filter()
把傳入的函數依次做用於每一個元素,而後根據返回值是True
仍是False
決定保留仍是丟棄該元素
一個序列中的空字符串刪掉,能夠這麼寫:
def not_empty(s): return s and s.strip() list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # 結果: ['A', 'B', 'C']
filter()
這個高階函數,關鍵在於正確實現一個「篩選」函數。 注意到filter()
函數返回的是一個Iterator
,也就是一個惰性序列,因此要強迫filter()
完成計算結果,須要用list()
函數得到全部結果並返回lis
def is_odd(n): return n % 2 == 1 tmplist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) newlist = list(tmplist) print(newlist)
sorted()
也是一個高階函數。用sorted()
排序的關鍵在於實現一個映射函數。
sorted函數:sorted(iterable,key,reverse)
其中iterable表示能夠迭代的對象, key是一個函數,用來選取參與比較的元素,reverse則是用來指定排序是倒序仍是順序,reverse=true則是倒序,reverse=false時則是順序,默認時reverse=false
如下返回值都是單一的key值排列或者value值排列