廖雪峰Python教程學習筆記4 函式式程式設計

2021-08-03 21:55:01 字數 4526 閱讀 9773

函式式程式設計就是一種抽象程度很高的程式設計正規化,其乙個特點是允許把函式本身作為引數傳入另乙個函式,還允許返回乙個函式!

把函式作為引數傳入,這樣的函式稱為高階函式,函式式程式設計就是指這種高度抽象的程式設計正規化。

既然變數可以指向函式,函式的引數能接收變數,那麼乙個函式就可以接收另乙個函式作為引數,這種函式就稱之為高階函式。

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

():print

'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 ...