2022-08-12 python函數(shù)式編程

本文引自極客時(shí)間:Python 核心技術(shù)與實(shí)戰(zhàn)10 | 簡約不簡單的匿名函數(shù) (geekbang.org)以及09 | 不可或缺的自定義函數(shù) (geekbang.org)

1. map()

map(function, iterable) 函數(shù),表示對 iterable 中的每個(gè)元素,都運(yùn)用 function 這個(gè)函數(shù),最后返回一個(gè)新的可遍歷的集合(map對象)。
例如:對列表中的每個(gè)元素乘以2

list1 = [1,2,3,4,5] #創(chuàng)建一個(gè)集合
new_list = map(lambda x: x * 2, list1) #使用map函數(shù)和lambda表達(dá)式對list1每個(gè)元素乘以2
print('new_list的類型是:',type(new_list), '\n')
for i in new_list:
    print(i)

運(yùn)行結(jié)果為:

new_list的類型是: <class 'map'> 

2
4
6
8
10

2. filter()

filter(function, iterable) 函數(shù),它和 map 函數(shù)類似,function 同樣表示一個(gè)函數(shù)對象。filter() 函數(shù)表示對 iterable 中的每個(gè)元素,都使用 function 判斷,并返回 True 或者 False,最后將返回 True 的元素組成一個(gè)新的可遍歷的集合(filter對象)。
例如:返回列表中的偶數(shù)

bool_list = filter(lambda x: x % 2 == 0, list1) #返回列表list中的偶數(shù)
print('bool_list的類型是:',type(bool_list), '\n') 
for i in bool_list:
    print(i)

運(yùn)行結(jié)果為:

bool_list的類型是: <class 'filter'> 

2
4

3. reduce()

reduce(function, iterable) 函數(shù),對 iterable 中的每個(gè)元素以及上一次調(diào)用后的結(jié)果,運(yùn)用 function 進(jìn)行計(jì)算,所以最后返回的是一個(gè)單獨(dú)的數(shù)值,它通常用來對一個(gè)集合做一些累積操作。
例如:計(jì)算某個(gè)列表元素的乘積


4. lambda()

具體應(yīng)用見這里:2022-08-12 python暑期面試題目 - 簡書 (jianshu.com)

5.函數(shù)的參數(shù)列表tips

  • 默認(rèn)參數(shù)
    函數(shù)的參數(shù)可以設(shè)置默認(rèn)值,傳入其他值則將其覆蓋掉:
# 參數(shù)的默認(rèn)值
def sum(a = 1, b = 2):
    return a + b
print(sum()) #可以不傳入?yún)?shù),函數(shù)采取默認(rèn)值計(jì)算
print(sum(2)) #傳入一個(gè)參數(shù),覆蓋掉第一個(gè)默認(rèn)值
print(sum(2,3)) #傳入兩個(gè)參數(shù),覆蓋掉兩個(gè)默認(rèn)值

運(yùn)行結(jié)果如下:

3
4
5
  • 函數(shù)的調(diào)用順序
    在外部主程序調(diào)用某個(gè)函數(shù)時(shí),必須保證該函數(shù)在前面已經(jīng)被定義,不然會(huì)報(bào)錯(cuò):
fun2() #先執(zhí)行后定義
def fun2():
    print('fun2被調(diào)用\n')

報(bào)錯(cuò):

NameError                                 Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 fun2()

NameError: name 'fun2' is not defined

但在函數(shù)內(nèi)部,函數(shù)間哪個(gè)聲明在前、哪個(gè)在后就無所謂,因?yàn)?def 是可執(zhí)行語句,函數(shù)在調(diào)用之前都不存在,我們只需保證調(diào)用時(shí),所需的函數(shù)都已經(jīng)聲明定義:

# 函數(shù)的互相調(diào)用
#fun2() 

def fun1():
    print('fun1函數(shù)被調(diào)用') #函數(shù)內(nèi)部調(diào)用另一個(gè)函數(shù)時(shí)只要后者被定義即可,順序不影響
    fun2()
    
    
def fun2():
    print('fun2函數(shù)被調(diào)用')
    
fun1() #這里主程序調(diào)用fun1()時(shí)仍需放在fun1()和fun2()之后,但fun1()里可先調(diào)用fun2()

運(yùn)行結(jié)果如下:

fun1函數(shù)被調(diào)用
fun2函數(shù)被調(diào)用
  • 函數(shù)的嵌套
    函數(shù)的嵌套便是在函數(shù)的內(nèi)部再定義函數(shù),以上面的fun1函數(shù)和fun2函數(shù)為例,要想主程序內(nèi)不能直接訪問fun2函數(shù),可將其定義放在fun1內(nèi)部,如下:
# 函數(shù)的嵌套
def fun1():
    print('fun1函數(shù)被調(diào)用\n')
    def fun2():
        print('fun2函數(shù)被調(diào)用\n')
    fun2()   # 在fun1()內(nèi)部調(diào)用fun2()

fun1()

運(yùn)行結(jié)果如下:

fun1函數(shù)被調(diào)用

fun2函數(shù)被調(diào)用
  • 函數(shù)變量作用域
    變量按照作用域分為全局變量與局部變量,全局變量在程序的任意位置均可訪問,局部變量只能在函數(shù)體內(nèi)被訪問。如下所示:
# 函數(shù)的作用域
# 函數(shù)的作用域
A = 2 # 全局變量
def fun3():
    a = 1; #局部變量
    print('函數(shù)內(nèi)訪問局部變量a: {}'.format(a))
    #global A
    #A = 3
    print('函數(shù)內(nèi)訪問全局變量A: {}'.format(A))

fun3()
print('函數(shù)外訪問全局變量A: {}'.format(A))
print('函數(shù)外訪問局部變量a: {}'.format(a))

運(yùn)行結(jié)果為:

函數(shù)內(nèi)訪問局部變量a: 1
函數(shù)內(nèi)訪問全局變量A: 2
函數(shù)外訪問全局變量A: 2
NameError: name 'a' is not defined

盡管能夠在函數(shù)內(nèi)部訪問全局變量,但要想在函數(shù)內(nèi)部修改全局變量必須先用關(guān)鍵字global聲明該全局變量,否則會(huì)報(bào)錯(cuò):

# 函數(shù)的作用域
A = 2 # 全局變量
def fun3():
    a = 1; #局部變量
    print('函數(shù)內(nèi)訪問局部變量a: {}'.format(a))
    print('函數(shù)內(nèi)訪問全局變量A: {}'.format(A))
    global A
    A = 3
    
fun3()
print('函數(shù)外訪問全局變量A: {}'.format(A))
#print('函數(shù)外訪問局部變量a: {}'.format(a))

上面程序會(huì)報(bào)錯(cuò),因?yàn)閷的全局聲明在其使用之后,如下:

name 'A' is used prior to global declaration

將聲明放在輸出語句前面:

# 函數(shù)的作用域
A = 2 # 全局變量
def fun3():
    a = 1; #局部變量
    print('函數(shù)內(nèi)訪問局部變量a: {}'.format(a))
    global A
    print('函數(shù)內(nèi)訪問全局變量A: {}'.format(A))
    A = 3
    
fun3()
print('函數(shù)外訪問全局變量A: {}'.format(A))
#print('函數(shù)外訪問局部變量a: {}'.format(a))

運(yùn)行結(jié)果如下:在函數(shù)外訪問的全局變量A已經(jīng)是被修改過的。

函數(shù)內(nèi)訪問局部變量a: 1
函數(shù)內(nèi)訪問全局變量A: 2
函數(shù)外訪問全局變量A: 3

在函數(shù)內(nèi)部定義與全局變量同名的局部變量會(huì)在函數(shù)體內(nèi)覆蓋掉此全局變量,但不影響其在其他地方的使用:

def fun4():
    A = 4 
    print('函數(shù)體內(nèi)A變量此時(shí)的值為: {}'.format(A))
fun4()
print('函數(shù)體外A變量此時(shí)的值為: {}'.format(A))

運(yùn)行結(jié)果如下,可以看到函數(shù)體內(nèi)輸出的A是被覆蓋后的值,函數(shù)體外輸出的A仍是原值。

函數(shù)體內(nèi)A變量此時(shí)的值為: 4
函數(shù)體外A變量此時(shí)的值為: 3

類似地,嵌套函數(shù)中內(nèi)部函數(shù)可以訪問外部函數(shù)的變量,但不能直接修改。若要修改,需加nonlocal關(guān)鍵字:

# 函數(shù)的嵌套
def fun1():
    B = 3
    print('fun1函數(shù)被調(diào)用',B)
    def fun2():
        nonlocal B # 聲明這里的B就是外部函數(shù)的B
        print('fun2函數(shù)被調(diào)用',B)
        B = 4 # 修改外部函數(shù)的變量
            
    fun2()   # 在fun1()內(nèi)部調(diào)用fun2()
    print('被修改后的B: {}'.format(B))

fun1()

運(yùn)行結(jié)果如下:

fun1函數(shù)被調(diào)用 3
fun2函數(shù)被調(diào)用 3
被修改后的B: 4
  • 閉包
    閉包與嵌套函數(shù)類似,但其外部函數(shù)的返回值是一個(gè)函數(shù),這個(gè)函數(shù)在后續(xù)會(huì)被賦予變量執(zhí)行計(jì)算。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容