1. 程式人生 > >Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式 Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式

Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式 Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式

Python之路Python作用域、匿名函式、函數語言程式設計、map函式、filter函式、reduce函式

一、作用域


return 可以返回任意值
例子

def test1():
    print("test1")
def test():
    print("test")
    return test1
res  = test()
print(res)

 

  

輸出結果

test
<function test1 at 0x021F5C90>

 

  


分析:這裡print(res)輸出的是test1函式在記憶體中的地址,return也是可以返回的


,加上括號就可以執行函數了

例子2

name = "pony"
def test1():
    name = "nicholas"
    def inner():
        name = "jack"
        print(name)
    return inner
res  = test1()
print(res)
res()

 

  

輸出結果

<function test1.<locals>.inner at 0x02195C48>
jack

 

  

分析:
test1函式返回了inner函式的記憶體地址,並被賦值給res,所以最後在res後加上括號就可以直接執行,注意這裡執行的是inner函式,列印name選擇的是區域性變數name ="jack",而非選擇呼叫執行的res()所在的name = "pony"


例子3

def foo():
    name = 'jack'
    def bar():
        name = 'pony'
        print(name)
        def tt():
            print(name)
        return tt
    
return bar r1 = foo() #返回的是bar函式的記憶體地址 r2 = r1() #執行了bar函式,返回了tt函式的記憶體地址 r3 = r2() #執行了tt函式,輸出 pony

 

  

輸出結果

pony
pony

 

  

分析:r1是執行foo函式,最後得到的是bar函式的記憶體地址,r2是執行了bar函式,返回了tt函式的記憶體地址,執行了tt函式,輸出 pony。
這裡也可以直接這樣寫
foo()()()
foo()是r1,foo()()是r2,foo()()()就是r3.

 

二、匿名函式

 

1、lambda

例子


lambda x:x+1
這裡的x相當於自定義函式的形參,x+1相當於return的返回值
def calc(x)
return x+1
這個自定義函式和lambda x:x+1是等價的

 

lambda函式一般用直接是處理加減法、乘法、加字串
例子

def calc(x):
    return x+1
res = calc(10)
print(res)
print(calc)

 

  

輸出結果

11
<function calc at 0x02245C48>

 

  

例子2

 

print(lambda x:x+1)

 


輸出結果

<function <lambda> at 0x021B5C48>

 

  

分析:這裡是lambda函式在記憶體中的地址,和calc函式是一樣的(未執行,即未加括號的情況下 )

呼叫lambda()

例子

func = lambda x:x+1
res = func(10)
print(res)

 

  

輸出

1  

  


分析:呼叫lambda函式需要將lambda函式賦值給一個變數,執行時用變數名加()帶引數執行,這裡括號內的引數類似自定義函式的實參,通過呼叫傳給形參。

 

例子3

print(list(filter(lambda x:x if x % 2 == 0 else "" ,range(10))))

 

  輸出結果

[2, 4, 6, 8]

 

  分析:lambda可以用if -else語句,但是不能單獨用if語句,必須if-else語句一起寫

 

2、lambda返回多個值


例子

func = lambda x,y,z:x + y + z
res = func(10,11,12)
print(res)
#或者這樣寫
print(func(10,11,12))

 

  

例子2

func = lambda x,y,z:(x + 1 ,y + 1,z +1)
res = func(10,11,12)
print(res)
#或者直接這樣寫
print(func(10,11,12))

 

  

輸出結果

(11, 12, 13)
(11, 12, 13)

 

  

分析:這裡返回多個值需要用括號和逗號


三、函數語言程式設計

 

1、程式設計的三種方法論

 

面向過程程式設計、函數語言程式設計、面向物件程式設計

面向過程:
定義
是一種以過程為中心的程式設計思想。這些都是以什麼正在發生為主要目標進行程式設計,不同於面向物件的是誰在受影響。
簡單的就是把任務分為一個一個的步驟,一步一步的執行。

 

函數語言程式設計:
定義
在計算機科學裡,函數語言程式設計是一種程式設計正規化,它將計算描述為表示式求值並避免了狀態和資料改變。函數語言程式設計裡面的“函式”指的是數學函式。

對於任何一個程式設計函式,需要滿足下面3個條件,即可轉換成純數學函式。

每個函式必須包含輸入引數(作為自變數)
每個函式必須有返回值(作為因變數)
無論何時,給定引數呼叫函式時,返回值必須一致。

 

面向物件程式設計
定義

面向物件程式設計——Object Oriented Programming,簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和操作資料的函式。

而面向物件的程式設計把計算機程式視為一組物件的集合,而每個物件都可以接收其他物件發過來的訊息,並處理這些訊息,計算機程式的執行就是一系列訊息在各個物件之間傳遞。


2、函數語言程式設計遞迴呼叫

高階函式的定義
(1)函式名可以當做引數傳遞
(2)返回值可以是引數


例子

def foo(n): #n=bar
    print(n)
 
def bar(name):
    print('my name is %s' %name)
foo(bar)
foo(bar("nicholas"))

 

  

輸出結果

<function bar at 0x02225C48>
my name is nicholas
None

 

  


分析:這裡的foo(bar),其中的bar是作為一個函式當做引數傳入foo(),bar是一個記憶體地址。foo(bar("nicholas"))中,bar("nicholas")執行函式,先輸出my name is nicholas,然後執行foo函式,由於bar函式沒有return出數值,所以執行foo()輸出None。


3、尾呼叫優化(尾遞迴優化)

尾呼叫:在函式的最後一步呼叫另外一個函式(最後一行不一定是函式的最後一步)

例子

def bar(n):
    return  n
def foo(x):
    return bar(x)

 

  


這裡的return bar()就是函式的最後一步。

例子

def test(x):
    if x > 1:
        return True
    elif x == 1:
        return False
    else:
        return False
test(1)

 

  

分析:這裡的最後一步是執行elif x ==1下面的 return False語句。

尾遞迴與非尾遞迴
非尾遞迴

def cal(seq):
    if len(seq) == 1:
        return  seq[0]
    head , *tail = seq
    return  head + cal(tail)
print(cal(range(100)))

 

  

尾遞迴

def cal(l):
    print(l)
    if len(l) == 1:
        return  l[0]
    frist,second,*args = l
    l[0] = frist + second
    l.pop(1)
    return cal(l)
x = cal([i for i in range(10)])
print(x)

 

  


3、 map()函式


map() 會根據提供的函式對指定序列做對映。

map(function, iterable, ...)
function -- 函式,有兩個引數
iterable -- 一個或多個序列
它有兩個引數,第一個引數為某個函式,第二個為可迭代物件。

例子
需求,將li1 = [1,3,4,5,7,10] 的每個元素變成自己的平方。


用for迴圈解決

li1 =   [1,3,4,5,7,10]
li = []
for i in li1:
    li.append(i ** 2)
res = li
print(res)

 

  

升級需求,處理多個列表,將列表的的每個元素變成自己的平方。

li1 =   [1,3,4,5,7,10]
def map_test():
    li = []
    for i in li1:
        li.append(i ** 2)
    return li
res = map_test(li1)
print(res)

 

  

繼續升級需求,將原列表的每個元素平方,組成新的列表

 

li1 =   [1,3,4,5,7,10]
def pow_test(n):
    return n ** 2
def map_test(fun,array):
    li = []
    for i in array:
        res = fun(i)
        li.append(res)
    return li
res1 = map_test(pow_test,li1)
print(res1)

 

  

分析:這裡的map_test函式的引數fun傳入的是一個函式,即這個map_test函式是高階函式,在map_test函式裡呼叫其他函式,對第二個傳入的物件進行處理。兩個這裡map_test()、pow_test()加在一起實現的功能就是map()函式的作用。


這裡可以用map()函式處理

 

li1 = [1,3,4,5,7,10]
res1 = list(map(lambda x:x**2,li1))
print(res1)

 

  

分析:map()函式的第一個引數是一個函式,即匿名函式,這裡不需要加括號執行,只是代表對一個引數的處理方式,map()第二個引數是待處理的可迭代物件。
map()函式直接處理結果是一個map()函式的記憶體地址,是一個可迭代型別,需要加list轉換為列表。

這裡map()函式的第一個引數不一定非要寫lambda函式,也可以寫自定義的函式名。


例子

 

def reduce_one(n):
    return n - 1
li1 =   [1,3,4,5,7,10]
res1 = list(map(reduce_one,li1))
print(res1)

 

  

輸出結果

[0, 2, 3, 4, 6, 9]

 

  



關於map()函式輸出的結果處理

例子
用for 迴圈處理結果

li1 =   [1,3,4,5,7,10]
res1 = map(lambda x:x**2,li1)
for i in res1:
    print(i)
print(res1)

 

  

輸出結果

1
9
16
25
49
100
<map object at 0x02185790>

 

  

直接用map函式

li1 = [1,3,4,5,7,10]
res = list(map(lambda x:x**2,li1))
print("map處理結果是",res)

 

  

輸出結果

 

map處理結果是 [1, 9, 16, 25, 49, 100]

 

  

分析:這裡可以看出map()函式直接輸出的結果是一個可迭代物件,加上list可以將其轉換為列表。


4、filter()函式


filter()函式是 Python 內建的另一個有用的高階函式,filter()函式接收一個函式 f 和一個list,這個函式 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
filter:過濾,濾除

例子
,要從一個list [1, 4, 6, 7, 9, 12, 17]中刪除偶數,保留奇數

用自定義函式和for迴圈解決

li = [1, 4, 6, 7, 9, 12, 17]
li1 = []
def filter_old(n):
    if n % 2 == 1:
        li1.append(n)
def test():
    for i in li:
        res = filter_old(i)
test()
print(li1)

 

  

輸出

[1, 7, 9, 17]

 

  

這裡也可以直接用filter函式解決。

li = [1, 4, 6, 7, 9, 12, 17]
def filter_old(n):
    if n % 2 == 1:
        return n
res = list(filter(filter_old,li))
print(res)

 

  


輸出結果

[1, 7, 9, 17]

 

  

或者更精簡一些

 

li = [1, 4, 6, 7, 9, 12, 17]
res = list(filter(lambda n:n %2 ==1,li))
print(res)

 

  

輸出結果

[1, 7, 9, 17]

 

  

分析:這裡的lambda函式是一個函式處理邏輯,最終是返回了符合 n %2 ==1條件的n
這裡與map函式一樣,也需要List將其轉換為列表。

例子

li = [1, 4, 6, 7, 9, 12, 17]
res = list(filter(lambda n:not n %2 ==1,li))
print(res)

 

  

分析:這裡的lambda也可以加not。

例子

li = [
    {"name":"jack","age":53},
    {"name":"pony","age":46},
    {"name":"charles","age":53},
    {"name":"richard","age":44}
 
]
v = list(filter(lambda p:p["age"]<45,li))
print(v)

 

  

輸出結果

[{'name': 'richard', 'age': 44}]

 

  

分析:這裡lambda返回的就是符合條件的元素p,遍歷序列中的每個元素,判斷每個元素得到布林值,如果是True則留下來。


5、reduce()函式


reduce()在python2中可以直接用
在python3中需要新增模組匯入
from functools import reduce

reduce()的使用方法形如reduce(f(x),Itera).對,它的形式和map()函式一樣。不過引數f(x)必須有兩個引數。reduce()函式作用是:把結果繼續和序列的下一個元素做累積計算。

例子
需求將列表[1,2,3,4,5,6]所有元素加起來。
用for迴圈解決

li = [1,2,3,4,5,6]
sum = 0
for i in li:
    sum = sum + i
print(sum)

 

  

需求2,求列表li = [1,2,3,4,5,6]每個元素相乘最終結果

用自定義函式處理

li = [1,2,3,4,5,6]
def test(x,y):
    return x*y
def test1(func,array):
    res = array.pop(0)
    #這裡表示列表的第一個元素
    #pop()刪除某個值,並可以獲取當前刪除的值
    for i in array:
        res = func(res,i)
        #這裡是傳入的相乘的結果和下一個元素,初始值為res = array[0]。
    return res
v = test1(test,li)
print(v)

 

  

輸出結果

720

 

分析:這裡是自定義了2個函式,通過函式中呼叫另一個函式處理。這裡也可以直接用reduce()函式處理。

rom functools import reduce
li = [1,2,3,4,5,6]
v = reduce(lambda x,y:x*y,li)
print(v)

 

  

輸出

720

 

  

分析:注意這裡不再使用list方法。

reduce 有 三個引數
function 有兩個引數的函式, 必需引數
sequence tuple ,list ,dictionary, string等可迭代物件,必需引數
initial 初始值, 可選引數

如果沒有初始值init,直接執行將第二個引數可迭代物件通過第一個引數func進行處理。
如果有初始值Init,則首先進行初始值和待傳入的第二個引數的第一個元素通過func進行處理,之後這個累計值再和第二個元素進行累計。

例子

from functools import reduce
li = [1,2,3,10]
v = reduce(lambda x,y:x*y,li,10)
print(v)

 

  


輸出結果

 

600

 

  


分析:這裡首先將初始值10 * 1 得到10,然後用累計值10 *2 得到20,然後20*3,以此類推,最後得到600.

 

6、map()、filter()、reduce()小結

map()
處理序列中的每個元素,得到的結果是一個‘列表’(記憶體地址),該‘列表’元素個數及位置與原來一樣

filter()
filter遍歷序列中的每個元素,判斷每個元素得到布林值,如果是True則留下來

reduce()

處理一個序列,然後把序列進行合併操作

 

一、作用域


return 可以返回任意值
例子

def test1():
    print("test1")
def test():
    print("test")
    return test1
res  = test()
print(res)

 

  

輸出結果

test
<function test1 at 0x021F5C90>

 

  


分析:這裡print(res)輸出的是test1函式在記憶體中的地址,return也是可以返回的
,加上括號就可以執行函數了

例子2

name = "pony"
def test1():
    name = "nicholas"
    def inner():
        name = "jack"
        print(name)
    return inner
res  = test1()
print(res)
res()

 

  

輸出結果

<function test1.<locals>.inner at 0x02195C48>
jack

 

  

分析:
test1函式返回了inner函式的記憶體地址,並被賦值給res,所以最後在res後加上括號就可以直接執行,注意這裡執行的是inner函式,列印name選擇的是區域性變數name ="jack",而非選擇呼叫執行的res()所在的name = "pony"


例子3

def foo():
    name = 'jack'
    def bar():
        name = 'pony'
        print(name)
        def tt():
            print(name)
        return tt
    return bar
r1 = foo() #返回的是bar函式的記憶體地址
r2 = r1()  #執行了bar函式,返回了tt函式的記憶體地址
r3 = r2()  #執行了tt函式,輸出 pony

 

  

輸出結果

pony
pony

 

  

分析:r1是執行foo函式,最後得到的是bar函式的記憶體地址,r2是執行了bar函式,返回了tt函式的記憶體地址,執行了tt函式,輸出 pony。
這裡也可以直接這樣寫
foo()()()
foo()是r1,foo()()是r2,foo()()()就是r3.

 

二、匿名函式

 

1、lambda

例子


lambda x:x+1
這裡的x相當於自定義函式的形參,x+1相當於return的返回值
def calc(x)
return x+1
這個自定義函式和lambda x:x+1是等價的

 

lambda函式一般用直接是處理加減法、乘法、加字串
例子

def calc(x):
    return x+1
res = calc(10)
print(res)
print(calc)

 

  

輸出結果

11
<function calc at 0x02245C48>

 

  

例子2

 

print(lambda x:x+1)

 


輸出結果

<function <lambda> at 0x021B5C48>

 

  

分析:這裡是lambda函式在記憶體中的地址,和calc函式是一樣的(未執行,即未加括號的情況下 )

呼叫lambda()

例子

func = lambda x:x+1
res = func(10)
print(res)

 

  

輸出

1  

  


分析:呼叫lambda函式需要將lambda函式賦值給一個變數,執行時用變數名加()帶引數執行,這裡括號內的引數類似自定義函式的實參,通過呼叫傳給形參。

 

例子3

print(list(filter(lambda x:x if x % 2 == 0 else "" ,range(10))))

 

  輸出結果

[2, 4, 6, 8]

 

  分析:lambda可以用if -else語句,但是不能單獨用if語句,必須if-else語句一起寫

 

2、lambda返回多個值


例子

func = lambda x,y,z:x + y + z
res = func(10,11,12)
print(res)
#或者這樣寫
print(func(10,11,12))

 

  

例子2

func = lambda x,y,z:(x + 1 ,y + 1,z +1)
res = func(10,11,12)
print(res)
#或者直接這樣寫
print(func(10,11,12))

 

  

輸出結果

(11, 12, 13)
(11, 12, 13)

 

  

分析:這裡返回多個值需要用括號和逗號


三、函數語言程式設計

 

1、程式設計的三種方法論

 

面向過程程式設計、函數語言程式設計、面向物件程式設計

面向過程:
定義
是一種以過程為中心的程式設計思想。這些都是以什麼正在發生為主要目標進行程式設計,不同於面向物件的是誰在受影響。
簡單的就是把任務分為一個一個的步驟,一步一步的執行。

 

函數語言程式設計:
定義
在計算機科學裡,函數語言程式設計是一種程式設計正規化,它將計算描述為表示式求值並避免了狀態和資料改變。函數語言程式設計裡面的“函式”指的是數學函式。

對於任何一個程式設計函式,需要滿足下面3個條件,即可轉換成純數學函式。

每個函式必須包含輸入引數(作為自變數)
每個函式必須有返回值(作為因變數)
無論何時,給定引數呼叫函式時,返回值必須一致。

 

面向物件程式設計
定義

面向物件程式設計——Object Oriented Programming,簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和操作資料的函式。

而面向物件的程式設計把計算機程式視為一組物件的集合,而每個物件都可以接收其他物件發過來的訊息,並處理這些訊息,計算機程式的執行就是一系列訊息在各個物件之間傳遞。


2、函數語言程式設計遞迴呼叫

高階函式的定義
(1)函式名可以當做引數傳遞
(2)返回值可以是引數


例子

def foo(n): #n=bar
    print(n)
 
def bar(name):
    print('my name is %s' %name)
foo(bar)
foo(bar("nicholas"))

 

  

輸出結果

<function bar at 0x02225C48>
my name is nicholas
None

 

  


分析:這裡的foo(bar),其中的bar是作為一個函式當做引數傳入foo(),bar是一個記憶體地址。foo(bar("nicholas"))中,bar("nicholas")執行函式,先輸出my name is nicholas,然後執行foo函式,由於bar函式沒有return出數值,所以執行foo()輸出None。


3、尾呼叫優化(尾遞迴優化)

尾呼叫:在函式的最後一步呼叫另外一個函式(最後一行不一定是函式的最後一步)

例子

def bar(n):
    return  n
def foo(x):
    return bar(x)

 

  


這裡的return bar()就是函式的最後一步。

例子

def test(x):
    if x > 1:
        return True
    elif x == 1:
        return False
    else:
        return False
test(1)

 

  

分析:這裡的最後一步是執行elif x ==1下面的 return False語句。

尾遞迴與非尾遞迴
非尾遞迴

def cal(seq):
    if len(seq) == 1:
        return  seq[0]
    head , *tail = seq
    return  head + cal(tail)
print(cal(range(100)))

 

  

尾遞迴

def cal(l):
    print(l)
    if len(l) == 1:
        return  l[0]
    frist,second,*args = l
    l[0] = frist + second
    l.pop(1)
    return cal(l)
x = cal([i for i in range(10)])
print(x)

 

  


3、 map()函式


map() 會根據提供的函式對指定序列做對映。

map(function, iterable, ...)
function -- 函式,有兩個引數
iterable -- 一個或多個序列
它有兩個引數,第一個引數為某個函式,第二個為可迭代物件。

例子
需求,將li1 = [1,3,4,5,7,10] 的每個元素變成自己的平方。


用for迴圈解決

li1 =   [1,3,4,5,7,10]
li = []
for i in li1:
    li.append(i ** 2)
res = li
print(res)

 

  

升級需求,處理多個列表,將列表的的每個元素變成自己的平方。

li1 =   [1,3,4,5,7,10]
def map_test():
    li = []
    for i in li1:
        li.append(i ** 2)
    return li
res = map_test(li1)
print(res)

 

  

繼續升級需求,將原列表的每個元素平方,組成新的列表

 

li1 =   [1,3,4,5,7,10]
def pow_test(n):
    return n ** 2
def map_test(fun,array):
    li = []
    for i in array:
        res = fun(i)
        li.append(res)
    return li
res1 = map_test(pow_test,li1)
print(res1)

 

  

分析:這裡的map_test函式的引數fun傳入的是一個函式,即這個map_test函式是高階函式,在map_test函式裡呼叫其他函式,對第二個傳入的物件進行處理。兩個這裡map_test()、pow_test()加在一起實現的功能就是map()函式的作用。


這裡可以用map()函式處理

 

li1 = [1,3,4,5,7,10]
res1 = list(map(lambda x:x**2,li1))
print(res1)

 

  

分析:map()函式的第一個引數是一個函式,即匿名函式,這裡不需要加括號執行,只是代表對一個引數的處理方式,map()第二個引數是待處理的可迭代物件。
map()函式直接處理結果是一個map()函式的記憶體地址,是一個可迭代型別,需要加list轉換為列表。

這裡map()函式的第一個引數不一定非要寫lambda函式,也可以寫自定義的函式名。


例子

 

def reduce_one(n):
    return n - 1
li1 =   [1,3,4,5,7,10]
res1 = list(map(reduce_one,li1))
print(res1)

 

  

輸出結果

[0, 2, 3, 4, 6, 9]

 

  



關於map()函式輸出的結果處理

例子
用for 迴圈處理結果

li1 =   [1,3,4,5,7,10]
res1 = map(lambda x:x**2,li1)
for i in res1:
    print(i)
print(res1)

 

  

輸出結果

1
9
16
25
49
100
<map object at 0x02185790>

 

  

直接用map函式

li1 = [1,3,4,5,7,10]
res = list(map(lambda x:x**2,li1))
print("map處理結果是",res)

 

  

輸出結果

 

map處理結果是 [1, 9, 16, 25, 49, 100]

 

  

分析:這裡可以看出map()函式直接輸出的結果是一個可迭代物件,加上list可以將其轉換為列表。


4、filter()函式


filter()函式是 Python 內建的另一個有用的高階函式,filter()函式接收一個函式 f 和一個list,這個函式 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
filter:過濾,濾除

例子
,要從一個list [1, 4, 6, 7, 9, 12, 17]中刪除偶數,保留奇數

用自定義函式和for迴圈解決

li = [1, 4, 6, 7, 9, 12, 17]
li1 = []
def filter_old(n):
    if n % 2 == 1:
        li1.append(n)
def test():
    for i in li:
        res = filter_old(i)
test()
print(li1)

 

  

輸出

[1, 7, 9, 17]

 

  

這裡也可以直接用filter函式解決。

li = [1, 4, 6, 7, 9, 12, 17]
def filter_old(n):
    if n % 2 == 1:
        return n
res = list(filter(filter_old,li))
print(res)

 

  


輸出結果

[1, 7, 9, 17]

 

  

或者更精簡一些

 

li = [1, 4, 6, 7, 9, 12, 17]
res = list(filter(lambda n:n %2 ==1,li))
print(res)

 

  

輸出結果

[1, 7, 9, 17]

 

  

分析:這裡的lambda函式是一個函式處理邏輯,最終是返回了符合 n %2 ==1條件的n
這裡與map函式一樣,也需要List將其轉換為列表。

例子

li = [1, 4, 6, 7, 9, 12, 17]
res = list(filter(lambda n:not n %2 ==1,li))
print(res)

 

  

分析:這裡的lambda也可以加not。

例子

li = [
    {"name":"jack","age":53},
    {"name":"pony","age":46},
    {"name":"charles","age":53},
    {"name":"richard","age":44}
 
]
v = list(filter(lambda p:p["age"]<45,li))
print(v)

 

  

輸出結果

[{'name': 'richard', 'age': 44}]

 

  

分析:這裡lambda返回的就是符合條件的元素p,遍歷序列中的每個元素,判斷每個元素得到布林值,如果是True則留下來。


5、reduce()函式


reduce()在python2中可以直接用
在python3中需要新增模組匯入
from functools import reduce

reduce()的使用方法形如reduce(f(x),Itera).對,它的形式和map()函式一樣。不過引數f(x)必須有兩個引數。reduce()函式作用是:把結果繼續和序列的下一個元素做累積計算。

例子
需求將列表[1,2,3,4,5,6]所有元素加起來。
用for迴圈解決

li = [1,2,3,4,5,6]
sum = 0
for i in li:
    sum = sum + i
print(sum)

 

  

需求2,求列表li = [1,2,3,4,5,6]每個元素相乘最終結果

用自定義函式處理

li = [1,2,3,4,5,6]
def test(x,y):
    return x*y
def test1(func,array):
    res = array.pop(0)
    #這裡表示列表的第一個元素
    #pop()刪除某個值,並可以獲取當前刪除的值
    for i in array:
        res = func(res,i)
        #這裡是傳入的相乘的結果和下一個元素,初始值為res = array[0]。
    return res
v = test1(test,li)
print(v)

 

  

輸出結果

720

 

分析:這裡是自定義了2個函式,通過函式中呼叫另一個函式處理。這裡也可以直接用reduce()函式處理。

rom functools import reduce
li = [1,2,3,4,5,6]
v = reduce(lambda x,y:x*y,li)
print(v)

 

  

輸出

720

 

  

分析:注意這裡不再使用list方法。

reduce 有 三個引數
function 有兩個引數的函式, 必需引數
sequence tuple ,list ,dictionary, string等可迭代物件,必需引數
initial 初始值, 可選引數

如果沒有初始值init,直接執行將第二個引數可迭代物件通過第一個引數func進行處理。
如果有初始值Init,則首先進行初始值和待傳入的第二個引數的第一個元素通過func進行處理,之後這個累計值再和第二個元素進行累計。

例子

from functools import reduce
li = [1,2,3,10]
v = reduce(lambda x,y:x*y,li,10)
print(v)

 

  


輸出結果

 

600

 

  


分析:這裡首先將初始值10 * 1 得到10,然後用累計值10 *2 得到20,然後20*3,以此類推,最後得到600.

 

6、map()、filter()、reduce()小結

map()
處理序列中的每個元素,得到的結果是一個‘列表’(記憶體地址),該‘列表’元素個數及位置與原來一樣

filter()
filter遍歷序列中的每個元素,判斷每個元素得到布林值,如果是True則留下來

reduce()

處理一個序列,然後把序列進行合併操作