1. 程式人生 > >《Python從小白到大牛》第10章 函數式編程

《Python從小白到大牛》第10章 函數式編程

apt users 出現 mod 聚合 pic 實例 參數形式 兩種

程序中反復執行的代碼可以封裝到一個代碼塊中,這個代碼塊模仿了數學中的函數,具有函數名、參數和返回值,這就是程序中的函數。

Python中的函數很靈活,它可以在模塊中,但類之外定義,即函數,作用域是當前模塊;也可以在別的函數中定義,即嵌套函數;還可以在類中定義,即方法。

定義函數

在前面的學習過程中也用到了一些函數,如果len()、min()和max(),這些函數都由Python官方提供的,稱為內置函數(Built-in
Functions, 縮寫BIF)。

註意
Python作為解釋性語言函數必須先定義後調用,也就是定義函數必須在調用函數之前,否則會有錯誤發生。

本節介紹自定義函數,自定義函數的語法格式如下:

def 函數名(參數列表) : 
    函數體
    return 返回值

在Python中定義函數時,關鍵字是def,函數名需要符合標識符命名規範;多個參數列表之間可以用逗號(,)分隔,當然函數也可以沒有參數。如果函數有返回數據,就需要在函數體最後使用return語句將數據返回;如果沒有返回數據,則函數體中可以使用return
None或省略return語句。

函數定義示例代碼如下:

# coding=utf-8
# 代碼文件:chapter10/ch10.1.py

def rectangle_area(width, height): ①
    area = width * height
    return area ②

r_area = rectangle_area(320.0, 480.0) ③

print("320x480的長方形的面積:{0:.2f}".format(r_area))

上述代碼第①行是定義計算長方形面積的函數rectangle_area,它有兩個參數,分別是長方形的寬和高,width和height是參數名。代碼第②行代碼是通過return返回函數計算結果。代碼第③行是調用rectangle_area函數。

函數參數

Python中的函數參數很靈活,具體體現在傳遞參數有多種形式上。本節介紹幾種不同形式參數和調用方式。

使用關鍵字參數調用函數

為了提高函數調用的可讀性,在函數調用時可以使用關鍵字參數調用。采用關鍵字參數調用函數,在函數定義時不需要做額外的工作。

示例代碼如下:

# coding=utf-8
# 代碼文件:chapter10/ch10.2.1.py

def print_area(width, height):
    area = width * height
    print("{0} x {1} 長方形的面積:{2}".format(width, height, area))

print_area(320.0, 480.0)  # 沒有采用關鍵字參數函數調用   ①
print_area(width=320.0, height=480.0)  # 采用關鍵字參數函數調用②
print_area(320.0, height=480.0)  # 采用關鍵字參數函數調用 ③
# print_area(width=320.0, height)  # 發生錯誤 ④
print_area(height=480.0, width=320.0)  # 采用關鍵字參數函數調用 ⑤

print_area函數有兩個參數,在調用時沒有采用關鍵字參數函數調用,見代碼第①行,也可以使用關鍵字參數調用函數,見代碼第②行、第③行和第⑤行,其中width和height是參數名。從上述代碼比較可見采用關鍵字參數調用函數,調用者能夠清晰地看出傳遞參數的含義,關鍵字參數對於有多參數函數調用非常有用。另外,采用關鍵字參數函數調用時,參數順序可以與函數定義時參數順序不同。

註意
在調用函數時,一旦其中一個參數采用了關鍵字參數形式傳遞,那麽其後的所有參數都必須采用關鍵字參數形式傳遞。代碼第④行的函數調用中第一個參數width采用了關鍵字參數形式,而它後面的參數沒有采用關鍵字參數形式,因此會有錯誤發生。

參數默認值

在定義函數的時候可以為參數設置一個默認值,當調用函數的時候可以忽略該參數。來看下面的一個示例:

# coding=utf-8
# 代碼文件:chapter9/ch10.2.2.py

def make_coffee(name="卡布奇諾"):
    return "制作一杯{0}咖啡。".format(name)

上述代碼定義了makeCoffee函數,可以幫助我做一杯香濃的咖啡。由於我喜歡喝卡布奇諾,就把它設置為默認值。在參數列表中,默認值可以跟在參數類型的後面,通過等號提供給參數。

在調用的時候,如果調用者沒有傳遞參數,則使用默認值。調用代碼如下:

coffee1 = make_coffee("拿鐵")  ①
coffee2 = make_coffee() ②

print(coffee1)  # 制作一杯拿鐵咖啡。
print(coffee2)  # 制作一杯卡布奇諾咖啡。

其中第①行代碼是傳遞"拿鐵"參數,沒有使用默認值。第②行代碼沒有傳遞參數,因此使用默認值。

提示
在其他語言中make_coffee函數可以采用重載實現多個版本。Python不支持函數重載,而是使用參數默認值的方式提供類似函數重載的功能。因為參數默認值只需要定義一個函數就可以了,而重載則需要定義多個函數,這會增加代碼量。

可變參數

Python中函數的參數個數可以變化,它可以接受不確定數量的參數,這種參數稱為可變參數。Python中可變參數有兩種,在參數前加*或**形式,*可變參數在函數中被組裝成為一個元組,**可變參數在函數中被組裝成為一個字典。

  1. *可變參數

下面看一個示例:

def sum(*numbers, multiple=1):
    total = 0.0
    for number in numbers:
        total += number
    return total * multiple

上述代碼定義了一個sum()函數,用來計算傳遞給它的所有參數之和。*numbers是可變參數。在函數體中參數numbers被組裝成為一個元組,可以使用for循環遍歷numbers元組,計算他們的總和,然後返回給調用者。

下面是三次調用sum()函數的代碼:

print(sum(100.0, 20.0, 30.0))  # 輸出150.0
print(sum(30.0, 80.0))  # 輸出110.0
print(sum(30.0, 80.0, multiple=2))  # 輸出220.0 ①

double_tuple = (50.0, 60.0, 0.0)  # 元組或列表 ②
print(sum(30.0, 80.0, *double_tuple))  # 輸出220.0 ③

可以看到,每次所傳遞參數的個數是不同的,前兩次調用時都省略了multiple參數,第三次調用時傳遞了multiple參數,此時multiple應該使用關鍵字參數傳遞,否則有錯誤發生。

如果已經有一個元組變量(見代碼第②行),能否傳遞給可變參數呢?這需要使用對元組進行拆包,見代碼第③行在元組double_tuple前面加上單星號(*),單星號在這裏表示將double_tuple拆包為50.0,
60.0, 0.0形式。另外,double_tuple也可以是列表對象。

註意
*可變參數不是最後一個參數時,後面的參數需要采用關鍵字參數形式傳遞。代碼第①行30.0,
80.0是可變參數,後面multiple參數需要關鍵字參數形式傳遞。

  1. **可變參數

下面看一個示例:

def show_info(sep=‘:‘, **info):
    print(‘-----info------‘)
    for key, value in info.items():
        print(‘{0} {2} {1}‘.format(key, value, sep))

上述代碼定義了一個show_info()函數,用來輸出一些信息,其中參數sep信息分隔符號,默認值是冒號(:)。**info是可變參數,在函數體中參數info被組裝成為一個字典。

註意 **可變參數必須在正規參數之後,如果本例函數定義改為show_info(**info,sep=‘:‘)形式,會發生錯誤。

下面是三次調用show_info()函數的代碼:

show_info(‘->‘, name=‘Tony‘, age=18, sex=True)  ①
show_info(sutdent_name=‘Tony‘, sutdent_no=‘1000‘, sep=‘-‘) ②

stu_dict = {‘name‘: ‘Tony‘, ‘age‘: 18}  # 創建字典對象 
show_info(**stu_dict, sex=True, sep=‘=‘)  # 傳遞字典stu_dict ③

上述代碼第①行是調用函數show_info(),第一個參數‘-\>‘是傳遞給sep,其後的參數name=‘Tony‘,
age=18,
sex=True是傳遞給info,這種參數形式事實上就是關鍵字參數,註意鍵不要用引號包裹起來。

代碼第②行是調用函數show_info(),sep也采用關鍵字參數傳遞,這種方式sep參數可以放置在參數列表的任何位置,其中的關鍵字參數被收集到info字典中。

代碼第③行是調用函數show_info(),其中字典對象stu_dict,傳遞時stu_dict前面加上雙星號(**),雙星號在這裏表示將stu_dict拆包為key=value對的形式。

函數返回值

Python函數的返回值也是比較靈活的,主要有三種形式:無返回值、單一返回值和多返回值。前面使用的函數基本都單一返回值,本節重點介紹無返回值和多返回值兩種形式。

無返回值函數

有的函數只是為了處理某個過程,此時可以將函數設計為無返回值的。所謂無返回值,事實上是返回None,None表示沒有實際意義的數據。

無返回值函數示例代碼如下:

# coding=utf-8
# 代碼文件:chapter9/ch10.3.1.py

def show_info(sep=‘:‘, **info): ①
    """定義**可變參數函數"""
    print(‘-----info------‘)
    for key, value in info.items():
        print(‘{0} {2} {1}‘.format(key, value, sep))
    return  # return None 或省略   ②

result = show_info(‘->‘, name=‘Tony‘, age=18, sex=True)
print(result)  # 輸出 None 

def sum(*numbers, multiple=1): ③
    """定義*可變參數函數"""
    if len(numbers) == 0:
        return  # return None 或省略 ④
    total = 0.0
    for number in numbers:
        total += number
    return total * multiple

print(sum(30.0, 80.0))  # 輸出110.0
print(sum(multiple=2)) # 輸出 None ⑥

上述代碼定義了兩個函數,這個兩個函數事實上是在10.3.2節示例基礎上的重構。其中代碼第①行的show_info()只是輸出一些信息,不需要返回數據,因此可以省略return語句。如果一定要使用return語句,見代碼第②行在函數結束前使用return或return
None。

對於本例中的show_info()函數強加return語句顯然是多此一舉,但是有時使用return或return
None是必要的。代碼第③行定義了sum()函數,如果numbers中數據是空的,後面的求和計算也就沒有意義了,可以在函數的開始判斷numbers中算法有數據,如果沒有數據則使用return或return
None跳出函數,見代碼第④行。

多返回值函數

有時需要函數返回多個值,實現返回多個值的實現方式有很多,簡單實現是使用元組返回多個值,因為元組作為數據結構可以容納多個數據,另外元組是不可變的,使用起來比較安全。

下面來看一個示例:

# coding=utf-8
# 代碼文件:chapter9/ch10.3.2.py

def position(dt, speed):  ①
    posx = speed[0] * dt  ②
    posy = speed[1] * dt  ③
    return (posx, posy)  ④

move = position(60.0, (10, -5)) ⑤

print("物體位移:({0}, {1})".format(move[0], move[1])) ⑥

這個示例是計算物體在指定時間和速度時的位移。第①行代碼是定義position函數,其中dt參數是時間,speed參數是元組類型,speed第一個元素X軸上的速度,speed第二個元素Y軸上的速度。position函數的返回值也是元組類型。

函數體中的第②行代碼是計算X方向的位移,第③行代碼是計算Y方向的位移。最後,第④行代碼將計算後的數據返回,(posx,
posy)是元組類型實例。

第⑤行代碼調用函數,傳遞的時間是60.0秒,速度是(10,
-5)。第⑥行代碼打印輸出結果,結果如下:

物體位移:(600.0, -300.0)

函數變量作用域

變量可以在模塊中創建,作用域是整個模塊,稱為全局變量。變量也可以在函數中創建,默認情況下作用域是整個函數,稱為局部變量。

示例代碼如下:

# coding=utf-8
# 代碼文件:chapter9/ch10.4.py

# 創建全局變量x
x = 20 ①

def print_value():
    print("函數中x = {0}".format(x)) ②

print_value()
print("全局變量x = {0}".format(x))

輸出結果:

函數中x = 20
全局變量x = 20

上述代碼第①行是創建全局變量x,全局變量作用域是整個模塊,所以在print_value()函數中也可以訪問變量x,見代碼第②行。

修改上述示例代碼如下:

# 創建全局變量x
x = 20 

def print_value():
    # 創建局部變量x
    x = 10  ①
    print("函數中x = {0}".format(x)) 

print_value()
print("全局變量x = {0}".format(x))

輸出結果:

函數中x = 10
全局變量x = 20

上述代碼的是print_value()函數中添加x =
10語句,見代碼第①行,這會函數中創建x變量,函數中的x變量與全局變量x命名相同,在函數作用域內會屏蔽全局x變量。

函數中創建的變量默認作用域是當前函數,這可以防止程序員少犯錯誤,因為函數中創建的變量,如果作用域是整個模塊,那麽在其他函數中也可以訪問,Python無法從語言層面定義常量,所以在其他函數中由於誤操作修改了變量,這樣一來很容易導致程序出現錯誤。即便筆者不贊同,但Python提供這種可能,通過在函數中將變量聲明為global的,可以把變量的作用域變成全局的。

修改上述示例代碼如下:

# 創建全局變量x
x = 20 

def print_value():
    global x  ①
    x = 10   ②
    print("函數中x = {0}".format(x)) 

print_value()
print("全局變量x = {0}".format(x))

輸出結果:

函數中x = 10
全局變量x = 10

代碼第①行是在函數中聲明x變量作用域為全局變量,所以代碼第②行修改x值,就是修改全局變量x的數值。

生成器

在一個函數中使用return關鍵字返回數據,但是有時候會使用yield?關鍵字返回數據。yield?關鍵字的函數返回的是一個生成器(generator)對象,生成器對象是一種可叠代對象。

如果想計算平方數列,通常的實現代碼如下:

def square(num):  ①
    n_list = []

    for i in range(1, num + 1):
        n_list.append(i * i) ②

    return n_list ③

for i in square(5):  ④
    print(i, end=‘ ‘)

返回結果是:

1 4 9 16 25

首先定義一個函數,見代碼第①行。代碼第②行通過循環計算一個數的平方,並將結果保存到一個列表對象n_list中。最後返回列表對象,見代碼第③行。代碼第④行是遍歷返回的列表對象。

在Python中還可以有更加好解決方案,實現代碼如下:

def square(num):

    for i in range(1, num + 1):
        yield i * i    ①

for i in square(5):  ②
    print(i, end=‘ ‘)

返回結果是:

1 4 9 16 25

代碼第①行使用了yield關鍵字返回平方數,不再需要return關鍵字了。代碼第②行調用函數square()返回的是生成器對象。生成器對象是一種可叠代對象,可叠代對象通過next()方法獲得元素,代碼第②行的for循環能夠遍歷可叠代對象,就是隱式地調用生成器的next()方法獲得元素的。

顯式地調用生成器的next()方法,在Python Shell中運行示例代碼如下:

>>> def square(num):

    for i in range(1, num + 1):
            yield i * i

>>> n_seq = square(5)
<generator object square at 0x000001C8F123CE60>
>>> n_seq.__next__()  ①
1
>>> n_seq.__next__()
4
>>> n_seq.__next__()
9
>>> n_seq.__next__()
16
>>> n_seq.__next__()
25
>>> n_seq.__next__() ②
Traceback (most recent call last):
  File "<pyshell#33>", line 1, in <module>
    n_seq.__next__()
StopIteration
>>>

上述代碼第①行\~第②行調用了6次next()方法,但第6次調用則會拋出StopIteration異常,這是因為已經沒有元素可叠代了。

生成器函數是通過yield返回數據,與return不同的是:return語句一次返回所有數據,函數調用結束;而yield語句只返回一個元素數據,函數調用不會結束,只是暫停,直到next()方法被調用,程序繼續執行yield語句之後的語句代碼。這個過程如圖10-1所示。

技術分享圖片

註意
生成器特別適合用於遍歷一些大序列對象,它無須將對象的所有元素都載入內存後才開始進行操作。而是僅在叠代至某個元素時才會將該元素載入內存。

嵌套函數

在本節之前定義的函數都是全局函數,並將他們定義在全局作用域中。函數還可定義在另外的函數體中,稱作“嵌套函數”。

示例代碼:

# coding=utf-8
# 代碼文件:chapter10/ch10.6.py

def calculate(n1, n2, opr):
    multiple = 2

    # 定義相加函數
    def add(a, b): ①
        return (a + b) * multiple

    # 定義相減函數
    def sub(a, b): ②
        return (a - b) * multiple

    if opr == ‘+‘:
        return add(n1, n2)
    else:
        return sub(n1, n2)

print(calculate(10, 5, ‘+‘))  # 輸出結果是30
# add(10, 5) 發生錯誤 ③
# sub(10, 5)  發生錯誤 ④

上述代碼中定義了兩個嵌套函數:add()和sub(),見代碼第①行和第②行。嵌套函數可以訪問所在外部函數calculate()中的變量multiple,而外部函數不能訪問嵌套函數局部變量。另外,嵌套函數的作用域在外部函數體內,因此在外部函數體之外直接訪問嵌套函數會發生錯誤,見代碼第③行和第④行。

函數式編程基礎

函數式編程(functional
programming)與面向對象編程一樣都一種編程範式,函數式編程,也稱為面向函數的編程。

Python並不是徹底的函數式編程語言,但是還是提供了一些函數式編程必備的技術,主要有:函數類型和Lambda表達式,他們是實現函數式編程的基礎。

函數類型

Python提供了一種函數類型function,任何一個函數都有函數類型,但是函數調用時,就創建了函數類型實例,即函數對象。函數類型實例與其他類型實例一樣,在使用場景上沒有區別:它可以賦值給一個變量;也可以作為參數傳遞給一個函數;還可以作為函數返回值使用。

為了理解函數類型,先重構10.6節中嵌套函數的示例,示例代碼如下:

# coding=utf-8
# 代碼文件:chapter10/ch10.7.1.py

def calculate_fun(opr): ①
    # 定義相加函數
    def add(a, b):
        return a + b

    # 定義相減函數
    def sub(a, b):
        return a - b

    if opr == ‘+‘:
        return add ②
    else:
        return sub ③

f1 = calculate_fun(‘+‘)  ④
f2 = calculate_fun(‘-‘)  ⑤

print(type(f1))

print("10 + 5 = {0}".format(f1(10, 5)))  ⑥
print("10 - 5 = {0}".format(f2(10, 5)))  ⑦

輸出結果:

<class ‘function‘>
10 + 5 = 30
10 - 5 = 10

上述代碼第①行重構了calculate_fun()函數的定義,現在只接收一個參數opr。代碼第②行是在opr

‘+‘為True時返回add函數名,否則返回sub函數名,見代碼第③行。這裏的函數名本質上函數對象。calculate_fun()函數與10.5節示例calculate()函數不同之處在於,calculate_fun()函數返回的是函數對象,calculate()函數返回的是整數(相加或相減計算之後的結果)。所以代碼第④行的f1是add()函數對象,代碼第⑤行的f2是sub()函數對象。

函數對象是可以與函數一樣進行調用的。事實上在第⑥行之前沒有真正調用add()函數進行相加計算,f1(10,
5)表達式才真的調用了add()函數。第⑦行的f2(10, 5)表達式是調用sub()函數。

Lambda表達式

理解了函數類型和函數對象,學習Lambda表達式就簡單了。Lambda表達式本質上一種匿名函數,匿名函數也是函數有函數類型,也可以創建函數對象。

定義Lambda表達式語法如下:

lambda 參數列表 : Lambda體

lambda是關鍵字聲明這是一個Lambda表達式,“參數列表”與函數的參數列表是一樣的,但不需要小括號包裹起來,冒號後面是“Lambda體”,Lambda表達式主要的代碼在此處編寫,類似於函數體。

註意
Lambda體部分不能是一個代碼塊,不能包含多條語句,只有一條語句,語句會計算一個結果返回給Lambda表達式,但是與函數不同是,不需要使用return語句返回。與其他語言中的Lambda表達式相比,Python中提供Lambda表達式只能處理一些簡單的計算。

重構10.7.1節示例,代碼如下:

# coding=utf-8
# 代碼文件:chapter10/ch10.7.2.py

def calculate_fun(opr):
    if opr == ‘+‘:
        return lambda a, b: (a + b) ①
    else:
        return lambda a, b: (a - b) ②

f1 = calculate_fun(‘+‘)
f2 = calculate_fun(‘-‘)

print(type(f1))

print("10 + 5 = {0}".format(f1(10, 5)))
print("10 - 5 = {0}".format(f2(10, 5)))

輸出結果:

<class ‘function‘>
10 + 5 = 30
10 - 5 = 10

上述代碼第①行替代了add()函數,第②行替代了sub()函數,代碼變的非常的簡單。

三大基礎函數

函數式編程本質是通過函數處理數據,過濾、映射和聚合是處理數據的三大基本操作。針對但其中三大基本操作Python提供了三個基礎的函數:filter()、map()和reduce()。

  1. filter()

過濾操作使用filter()函數,它可以對可叠代對象的元素進行過濾,filter()函數語法如下:

filter(function, iterable)

其中參數function是一個函數,參數iterable是可叠代對象。filter()函數調用時iterable會被遍歷,它的元素逐一傳入function函數,function函數返回布爾值,在function函數中編寫過濾條件,如果為True的元素被保留,如果為False的元素被過濾掉。

下面通過一個示例介紹一下filter()函數使用,示例代碼如下:

users = [‘Tony‘, ‘Tom‘, ‘Ben‘, ‘Alex‘]

users_filter = filter(lambda u: u.startswith(‘T‘), users) ①
print(list(users_filter))

輸出結果:

[‘Tony‘, ‘Tom‘]

代碼第①行調用filter()函數過濾users列表,過濾條件是T開通的元素,lambda u:
u.startswith(‘T‘)是一個Lambda表達式,它提供了過濾條件。filter()函數還不是一個列表,需要使用list()函數轉換過濾之後的數據為列表。

再看一個示例:

number_list = range(1, 11)
nmber_filter = filter(lambda it: it % 2 == 0, number_list)
print(list(nmber_filter))

該示例實現了獲取1\~10數字中的偶數,輸出結果如下:

[2, 4, 6, 8, 10]
  1. map()

映射操作使用map()函數,它可以對可叠代對象的元素進行變換,map()函數語法如下:

map(function, iterable)

其中參數function是一個函數,參數iterable是可叠代對象。map()函數調用時iterable會被遍歷,它的元素逐一傳入function函數,在function函數中對元素進行變換。

下面通過一個示例介紹一下map()函數使用,示例代碼如下:

users = [‘Tony‘, ‘Tom‘, ‘Ben‘, ‘Alex‘]

users_map = map(lambda u: u.lower(), users) ①  
print(list(users_map))

輸出結果:

[‘tony‘, ‘tom‘, ‘ben‘, ‘alex‘]

上述代碼第①行調用map()函數將users列表元素轉換為小寫字母,變換使用Lambda表達式lambda
u:
u.lower()。map()函數返回的還不是一個列表,需要使用list()函數將過濾之後的數據轉換為列表。

函數式編程時數據可以從一個函數“流”入另外一個函數,但是遺憾的是Python並不支持“鏈式”API。例如想獲取users列表中“T”開通的名字,再將其轉換為小寫字母,這樣的需求需要使用filter()函數進行過濾,再使用map()函數進行映射變換。實現代碼如下:

users = [‘Tony‘, ‘Tom‘, ‘Ben‘, ‘Alex‘]

users_filter = filter(lambda u: u.startswith(‘T‘), users)

# users_map = map(lambda u: u.lower(), users_filter) ①
users_map = map(lambda u: u.lower(), filter(lambda u: u.startswith(‘T‘), users)) ②

print(list(users_map))

上述代碼第①行和第②行實現相同功能。

  1. reduce()

聚合操作會將多個數據聚合起來輸出單個數據,聚合操作中最基礎的是歸納函數reduce(),reduce()函數會將多個數據按照指定的算法積累疊加起來,最後輸出一個數據。

reduce()函數語法如下:

reduce(function, iterable[, initializer])

參數function是聚合操作函數,該函數有兩個參數,參數iterable是可叠代對象;參數initializer初始值。

下面通過一個示例介紹一下reduce()函數使用。下面示例實現了對一個數列求和運算,代碼如下:

from functools import reduce ①

a = (1, 2, 3, 4)
a_reduce = reduce(lambda acc, i: acc + i, a)  # 10 ②
# a_reduce = reduce(lambda acc, i: acc + i, a, 2)  # 12 ③
print(a_reduce)

reduce()函數是在functools模塊中定義的,所以要使用reduce()函數需要導入functools模塊,見代碼第①行。代碼第②行是調用reduce()函數,其中lambda
acc, i: acc +
i是進行聚合操作的Lambda表達式,該Lambda表達式有兩個參數,其中acc參數是上次累積計算結果,i當前元素,acc
+
i表達式是進行累加。reduce()函數最後的計算結果是一個數值,直接可以使用通過reduce()函數返回。代碼第行是傳入了初始值2,則計算的結果是12。

本章小結

通過對本章內容的學習,讀者可以熟悉在Python中如何定義函數、函數參數和函數返回值,了解函數變量作用域和嵌套函數。最後還介紹了Python中函數式編程基礎。

配套視頻

http://edu.51cto.com/topic/1507.html

配套源代碼

http://www.zhijieketang.com/group/8

作者微博:@tony_關東升郵箱:[email protected]
br/>郵箱:[email protected]
Python讀者服務QQ群:628808216

《Python從小白到大牛》第10章 函數式編程