1. 程式人生 > >python高階函式,map,filter,reduce,ord,以及lambda表示式

python高階函式,map,filter,reduce,ord,以及lambda表示式

為什麼我突然扯出這麼幾個函式,是因為我今天在看流暢的python這本書的時候,裡面有一部分內容看的有點懵逼。

>>> symbols = '$¢£¥€¤'
>>> beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
>>> beyond_ascii
[162, 163, 165, 8364, 164]
>>> beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))
>>> beyond_ascii [162, 163, 165, 8364, 164]

下面根據這裡面的所有的函式展開整理一下

1.ord是將字元轉換為10進位制的數

2.而map是將列表內元素當做某個函式的引數得到的結果組成的新列表 

3.filter是將一個列表按照一定的規則過濾生成的列表

 

1.lambda表示式

ambda表示式,通常是在需要一個函式,但是又不想費神去命名一個函式的場合下使用,也就是指匿名函式

示例:

add = lambda x, y : x+y
add(1,2)  # 結果為3

1.1應用在函數語言程式設計中

Python提供了很多函數語言程式設計的特性,如:map、reduce、filter、sorted等這些函式都支援函式作為引數,lambda函式就可以應用在函數語言程式設計中。如下:

# 需求:將列表中的元素按照絕對值大小進行升序排列
list1 = [3,5,-4,-1,0,-2,-6]
sorted(list1, key=lambda x: abs(x))

當然,也可以如下:

list1 = [3,5,-4,-1,0,-2,-6]
def get_abs(x):
    return abs(x)
sorted(list1,key=get_abs)

只不過這種方式的程式碼看起來不夠Pythonic

1.2應用在閉包中

def get_y(a,b):
     return lambda x:ax+b
y1 = get_y(1,1)
y1(1) # 結果為2

當然,也可以用常規函式實現閉包,如下:

def get_y(a,b):
    def func(x):
        return ax+b
    return func
y1 = get_y(1,1)
y1(1) # 結果為2

只不過這種方式顯得有點囉嗦。

那麼是不是任何情況下lambda函式都要比常規函式更清晰明瞭呢?

肯定不是。

Python之禪中有這麼一句話:Explicit is better than implicit(明瞭勝於晦澀),就是說那種方式更清晰就用哪一種方式,不要盲目的都使用lambda表示式。

2.Map函式

map()函式接收兩個引數,一個是函式,一個是序列,map將傳入的函式依次作用到序列的每個元素,並把結果作為新的list返回。
舉例說明
比如我們有一個函式f(x)=x2,要把這個函式作用在一個list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()實現如下:

現在,我們用Python程式碼實現:

>>> 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]

map()傳入的第一個引數是f,即函式物件本身。 
你可能會想,不需要map()函式,寫一個迴圈,也可以計算出結果:

L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
    L.append(f(n))print L

的確可以,但是,從上面的迴圈程式碼,能一眼看明白“把f(x)作用在list的每一個元素並把結果生成一個新的list”嗎?
所以,map()作為高階函式,事實上它把運算規則抽象了,因此,我們不但可以計算簡單的f(x)=x2,還可以計算任意複雜的函式,比如,把這個list所有數字轉為字串:

>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
['1', '2', '3', '4', '5', '6', '7', '8', '9']

只需要一行程式碼。

3.Reduce函式 

reduce把一個函式作用在一個序列[x1, x2, x3…]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比方說對一個序列求和,就可以用reduce實現:

>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

當然求和運算可以直接用Python內建函式sum(),沒必要動用reduce。 
但是如果要把序列[1, 3, 5, 7, 9]變換成整數13579,reduce就可以派上用場:

>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579

這個例子本身沒多大用處,但是,如果考慮到字串str也是一個序列,對上面的例子稍加改動,配合map(),我們就可以寫出把str轉換為int的函式:

>>> def fn(x, y):
...     return x * 10 + y
...
>>> 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]
...
>>> reduce(fn, map(char2num, '13579'))
13579

整理成一個str2int的函式就是:

def str2int(s):

    def fn(x, y):
        return x * 10 + y

    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]

    return reduce(fn, map(char2num, s))

還可以用lambda函式進一步簡化成:

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 str2int(s):
    return reduce(lambda x,y: x*10+y, map(char2num, s))

也就是說,假設Python沒有提供int()函式,你完全可以自己寫一個把字串轉化為整數的函式,而且只需要幾行程式碼!

4.Filter函式 

Python內建的filter()函式用於過濾序列。

和map()類似,filter()也接收一個函式和一個序列。和map()不同的時,filter()把傳入的函式依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。

 True保留,False丟棄 
例如,在一個list中,刪掉偶數,只保留奇數,可以這麼寫:

def is_odd(n):
    return n % 2 == 1

filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])

# 結果: [1, 5, 9, 15]

把一個序列中的空字串刪掉,可以這麼寫:

def not_empty(s):
    return s and s.strip()

filter(not_empty, ['A', '', 'B', None, 'C', '  '])

# 結果: ['A', 'B', 'C']

可見用filter()這個高階函式,關鍵在於正確實現一個“篩選”函式。

5.ord函式

ord() 函式是 chr() 函式(對於8位的ASCII字串)或 unichr() 函式(對於Unicode物件)的配對函式,它以一個字元(長度為1的字串)作為引數,返回對應的 ASCII 數值,或者 Unicode 數值,如果所給的 Unicode 字元超出了你的 Python 定義範圍,則會引發一個 TypeError 的異常。

描述

ord() 函式是 chr() 函式(對於8位的ASCII字串)或 unichr() 函式(對於Unicode物件)的配對函式,它以一個字元(長度為1的字串)作為引數,返回對應的 ASCII 數值,或者 Unicode 數值,如果所給的 Unicode 字元超出了你的 Python 定義範圍,則會引發一個 TypeError 的異常。

語法

以下是 ord() 方法的語法:

ord(c)

引數

  • c -- 字元。

返回值

返回值是對應的十進位制整數

例項

以下展示了使用 ord() 方法的例項:

>>>ord('a')
97
>>> ord('b')
98
>>> ord('c')
99