函式式程式設計就是一種抽象程度很高的程式設計正規化,其乙個特點是允許把函式本身作為引數傳入另乙個函式,還允許返回乙個函式!
把函式作為引數傳入,這樣的函式稱為高階函式,函式式程式設計就是指這種高度抽象的程式設計正規化。
既然變數可以指向函式,函式的引數能接收變數,那麼乙個函式就可以接收另乙個函式作為引數,這種函式就稱之為高階函式。
e.g.傳入函式
def
add(x, y, f):
return f(x) + f(y)
當呼叫add(-5,6,abs)
時,高階函式的計算過程如下:
x ==> -5
y ==> 6
f ==> abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
1.map()函式
map()
函式接收兩個引數,乙個是函式,乙個是序列,map將傳入的函式依次作用到序列的每個元素,並把結果作為新的list返回。map()
作為高階函式,把運算規則抽象了,可以用它計算任意複雜的函式。
e.g.
>>> def f(x):
...return x * x
...>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]
2.reduce()函式
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)#跟迭代差不多
e.g.
#利用map()函式輕鬆實現字串轉整型
defstr2int
(s):
deffn
(x, y):
return x * 10 + y
defchar2num
(s):
return [s]
return reduce(fn, map(char2num, s))
python內建的filter()
函式用於過濾序列。
和map()
類似,filter()
也接收乙個函式和乙個序列。和map()
不同的時,filter()
把傳入的函式依次作用於每個元素,然後根據返回值是true還是false決定保留還是丟棄該元素。
e.g.
def
is_odd
(n):
return n % 2 == 1
filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
# 結果: [1, 5, 9, 15]
用filter()
函式關鍵在於正確實現乙個「篩選」函式。
python內建的sorted()
函式就可以對list進行排序:
>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]
此外,sorted()
函式也是乙個高階函式,它還可以接收乙個比較函式來實現自定義的排序。
e.g.
def
reversed_cmp
(x, y):
if x > y:
return -1
if x < y:
return
1return
0>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]
高階函式除了可以接受函式作為引數外,還可以把函式作為結果值返回。
e.g.
#返回求和的函式
deflazy_sum
(*args):
defsum
(): ax = 0
for n in args:
ax = ax + n
return ax
return sum
#當呼叫lazy_sum()時,返回的並不是求和結果,而是求和函式
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
0x10452f668>
#呼叫函式f時,才真正計算求和的結果
>>>f()
25
在這個例子中,我們在函式lazy_sum
中又定義了函式sum
,並且,內部函式sum
可以引用外部函式lazy_sum
的引數和區域性變數,當lazy_sum
返回函式sum
時,相關引數和變數都儲存在返回的函式中,這種稱為「閉包(closure)」的程式結構擁有極大的威力。需要注意的問題是,返回的函式並沒有立刻執行,而是直到呼叫了f()才執行。
可以認為閉包 = 函式 + 引用環境,也就是說,當形成乙個閉包之後,放進閉包的並不是具體的值。
e.g.
def
count
(): fs =
for i in range(1, 4):
deff():
return i*i
return fs
f1, f2, f3 = count()
#實際呼叫結果是f1()、f2()、f3()的結果都是9
>>> f1()
9>>> f2()
9>>> f3()
9
以這一節的例子來看,閉包中應該只包含變數i的位址,告訴程式當它被呼叫時這個i應該從**找,此時並不涉及i的值。只有當真正呼叫時,才根據此時i的值算出最終結果,而此時在返回3個函式之後,i的值已經成為3了,所以當我們開始呼叫函式時,返回的值就都是9了。
返回閉包時牢記的一點就是:返回函式不要引用任何迴圈變數,或者後續會發生變化的變數。
匿名函式就是不需要顯示地定義函式,在有時會很方便。
匿名函式lambda x:x*x
相當於
def
f(x):
return x*x
關鍵字lambda
表示匿名函式,冒號前面的x
表示函式引數。
匿名函式有個限制,就是只能有乙個表示式,不用寫return
,返回值就是該表示式的結果。
此外,匿名函式也是乙個函式物件,也可以把匿名函式賦值給乙個變數,再利用變數來呼叫該函式,或者把匿名函式作為返回值返回。
在**執行期間動態增加功能的方式被稱為「裝飾器」(decorator)。比如,要增強某個函式的功能,在函式呼叫前後自動列印日誌,但又不希望修改該函式的定義,就可寫乙個裝飾器。
本質上,decorator就是乙個返回函式的高階函式。可以定義如下:
import functools
deflog
(func):
@functools.wraps(func)
def(*args, **kw):
print
'call %s():' % func.__name__
return func(*args, **kw)
借助python的@語法,把decorator置於函式的定義處:
@log #相當於執行了語句now=log(now)呼叫defnow
'2013-12-25'
now()
函式,不僅會執行now()
函式本身,還會在執行now()
函式前列印一行日誌:
>>> now()
call
now():
2013-12-25
偏函式functools.partial
是python的functools
模組提供的諸多有用功能之一,其作用是把乙個函式的某些引數給固定住(也就是設定為預設值),返回乙個新函式,呼叫這個新函式會更簡單。
e.g.
>>>
import functools
>>> int2 = functools.partial(int, base=2)#將型別轉換的int(x,base)函式的基引數base固定為二進位制
>>> int2('1000000')
64>>> int2('1010101')
85
偏函式可以接收函式物件、*args
和**kw
這3個引數,上面的例子相當於接收了函式物件和**kw
引數。 python廖雪峰教程 學習筆記
如何用字元來描述字元 d匹配數字 digit w匹配字母或數字 word s可以匹配空格 space 表示任意個字元,表示至少乙個字元 表示0個或1個字元,表示n個字元,表示n m個字元 可以匹配任意字元 例如 kongxiangyu w如何做到更精確的匹配?規定數字 字母或者下劃線 0 9a za...
廖雪峰python教程學習筆記(函式)
1.max函式可以接收任意多個引數,並返回最大的那個 2.函式名其實就是指向乙個函式物件的引用,完全可以把函式名賦給乙個變數,相當於給這個函式起了乙個別名 3.在python中,定義乙個函式要用def語句,依次寫出函式名 括號 括號中的引數和冒號,然後在縮排塊中編寫函式體,函式的返回值用return...
廖雪峰python教程筆記1
d.get thomas 1 檢查字典中是否有 thomas 的key,沒有返回 1,沒有指定返回值預設返回none d.pop bob 刪key 字典key不能為列表 s set 1,2,3 set需要以list作為輸入集合,不能重複且無順序。s.add s.remove s1 s2 s1 s2 ...