1、什麼是偏函數?python
(1)在Python的functools模塊衆多的功能中,其中有一個就是偏函數,咱們稱之爲 partial function數組
模塊的概念咱們下一篇在細講。函數
(2)咱們都聽過偏將軍吧,在三國時代的官制中,系將軍的輔佐,與裨將軍二者都爲雜號將軍;今天咱們要講的偏函數,實際上是函數的輔佐,什麼意思呢,咱們藉助Python的help幫助函數,看一下:spa
這裏咱們主要說下紅色圈的意思:3d
partial 一共有三個部分:code
(1)第一部分也就是第一個參數,是一個函數,這個函數能夠是你定義的,也能夠是Python內置函數blog
(2)第二部分是一個可變參數,*args,好比內置函數max的參數就是一個可變參數,max(1,2,3,4,5)=5io
(3)第三部分是一個關鍵字參數,好比內置函數int的第二個參數就是命名關鍵字參數,默認base=10,表示int轉換時默認是10進制的:function
partial函數的做用就是:將所做用的函數做爲partial()函數的第一個參數,原函數的各個參數依次做爲partial()函數的後續參數,原函數有關鍵字參數的必定要帶上關鍵字,沒有的話,按原有參數順序進行補充。class
文字描述顯得有些無力,咱們下面就開始講一下,偏函數是怎麼用的
2、偏函數的使用
A、偏函數的第二個部分(可變參數),按原有函數的參數順序進行補充,參數將做用在原函數上,最後偏函數返回一個新函數(相似於,裝飾器decorator,對於函數進行二次包裝,產生特殊效果;但又不一樣於裝飾器,偏函數產生了一個新函數,而裝飾器,可改變被裝飾函數的函數入口地址也能夠不影響原函數)
案例:咱們定義一個sum函數,參數爲*args可變,計算這些可變參數的和。
擴展:咱們想要對sum函數求和後的結果,再加上10加上20甚至加更多,獲得一個新的結果
實現:咱們分別用decorator和partial來實現,對比一下兩者的區別
(一)裝飾器 decorator 實現
咱們上一篇,剛剛學過decorator,因此這裏,咱們直接看demo,應該會以爲很容易上手和理解:
test.py
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
from functools import wraps
def sum_add(*args1): #咱們要給咱們的裝飾器decorator,帶上參數
def decorator(func):
@wraps(func) #加上這句,原函數func被decorator做用後,函數性質不變
def my_sum(*args2): #注意,參數要和原函數保持一致,真正實行擴展功能的是外層的裝飾器
my_s = 0
for n in args1:
my_s = my_s +n #這個是咱們新加的求和結果
return func(*args2) + my_s #這個,咱們在原求和函數的結果上再加上s,並返回這個值
return my_sum #返回my_sum函數,該函數擴展原函數的功能
return decorator #返回咱們的裝飾器
@sum_add(10,20) #啓用裝飾器 對sum函數進行功能擴展
def sum(*args):
s = 0
for n in args:
s = s+n
return s
print(sum(1,2,3,4,5))
print(sum.__name__)
sum(1,2,3,4,5)返回的結果毫不是15,這樣就失去了裝飾器存在的意義,固然,這裏,咱們知道,sum最後返回的值應該是10+20+15 = 45,這樣一來,咱們的decorator就實現了咱們想要的擴展功能,最後,發現,原函數sum的name屬性,仍然是sum,說明,這種裝飾擴展功能,不影響咱們的原函數:
(二)偏函數 partial function 實現
這纔是咱們本篇的重點,準備好了,咱們就開始:
咱們先來看下普通函數,咱們是怎麼來實現
A:普通函數可變參數順序執行
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
def sum(*args):
s = 0
for n in args:
s = s + n
return s
print(sum(10,20)+sum(1,2,3,4,5))
咱們若是想實現+10+20的效果,必須寫兩遍sum,這樣寫,顯然是最易懂的,可是,卻顯得很邋遢不專業,咱們看下結果:
B:普通函數可變參數加關鍵字參數組合
針對上面的A過程,咱們改下代碼,使咱們的代碼看起來稍顯複雜,可是略顯專業:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
def sum(*args,**others):
s = 0
for n in args:
s = s + n
s1 = 0
for k in others:
s1 = s1 + others[k] #咱們還要算一下,關鍵字參數裏蘊藏的求和結果,k是dict中的關鍵字key
return s+s1 #最終,咱們實現擴展功能,順序參數和關鍵字參數結果相加
D= {'value1':10,'value2':20}
print(sum(1,2,3,4,5,**D))
代碼看起來,是顯得專業了,可是感受冗餘,不必,複雜不是咱們Python的風格,咱們看下B的結果:
C:偏函數可變參數順序填充一步到位
上面A和B咱們都說過了,這兩種方式都很差,顯然,這麼簡單的事情,咱們沒必要麻煩decorator了,那咱們還有辦法沒?有,Python,給咱們提供了偏函數,來吧,主角登場:
提示:兩種使用partial功能方式
(1)import functools -->functools.partial(func,*args)
(2)from functools import partial -->partial(func,*args)
咱們這裏選第二種,咱們看下demo:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
from functools import partial
def sum(*args):
s = 0
for n in args:
s = s + n
return s
sum_add_10 = partial(sum,10) #10 做用在sum第一個參數的位置
sum_add_10_20 = partial(sum,10,20) #10 20 分別做用在sum第一個和第二個參數的位置
print('A____________咱們看下原函數sum的函數地址入口:')
print(sum)
print('B______咱們看下partial函數返回函數的地址入口:')
print(partial(sum,10))
print(sum_add_10(1,2,3,4,5)) # --> 10 + 1 + 2 + 3 + 4 + 5 = 25
print(sum_add_10_20(1,2,3,4,5)) # --> 10 + 20 + 1 + 2 + 3 + 4 + 5 = 45
上面,能夠看出,咱們針對sum函數的求和結果,再加上10,或者加10加20,甚至加更多,都是能夠經過偏函數來實現的,注意偏函數的第二部分,參數是可變的,是按順序走的,所以,偏函數產生的新函數,sum_add_10 實際上等同於sum(10,*args):
經過幾個例子,咱們最終發現,仍是偏函數比較方便,一行代碼就搞定了,並且新定義的函數,能夠根據函數名很容易知道,這個函數擴展的原函數是哪一個,實現的效果是什麼:
B、偏函數的第三個部分(關鍵字參數),按原有函數的關鍵字參數進行填補,參數將做用在原函數上,最後偏函數返回一個新函數
案例:咱們定義一個mod求餘函數,兩個參數,一個是被除數,一個是除數,除數咱們這裏用命名關鍵字參數表示,默認值2
擴展:咱們的除數不固定,能夠是對2就行求餘,也能夠對3,對4,總之咱們須要指定除數的值
返回結果: True 或 False
實現:原函數實現和partial函數實現
demo以下:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
import functools
def mod(m,*,key=2):
return m % key == 0
mod_to_2 = functools.partial(mod,key=2)
print('A__3___使用原函數的默認關鍵字參數對2進行求餘:')
print(mod(3)) #對2進行求餘-- 原函數 使用默認參數
print('B__3___使用偏函數對2進行求餘:')
print(mod_to_2(3)) #對2進行求餘-- 新函數 --偏函數產生
mod_to_5 = functools.partial(mod,key=5)
print('C__25___使用原函數的關鍵字參數對5進行求餘:')
print(mod(25,key=5)) #對5進行求餘 -- 原函數
print('D__25___使用偏函數對5進行求餘:')
print(mod_to_5(25)) #對5進行求餘 -- 新函數--偏函數產生
咱們看下結果:
咱們發現,實際上,偏函數的做用,其實和原函數差很少,只不過,咱們要屢次調用原函數的時候,有些參數,咱們須要屢次手動的去提供值,好比上述的對5進行求餘,若是咱們想知道,15,45,30這些數是否可以被5整除,那麼,咱們用原函數的話,就須要寫三次,key=5,然而,咱們用偏函數的話,只須要重複調用新產生的函數mo
1、什麼是偏函數?
(1)在Python的functools模塊衆多的功能中,其中有一個就是偏函數,咱們稱之爲 partial function
模塊的概念咱們下一篇在細講。
(2)咱們都聽過偏將軍吧,在三國時代的官制中,系將軍的輔佐,與裨將軍二者都爲雜號將軍;今天咱們要講的偏函數,實際上是函數的輔佐,什麼意思呢,咱們藉助Python的help幫助函數,看一下:
這裏咱們主要說下紅色圈的意思:
partial 一共有三個部分:
(1)第一部分也就是第一個參數,是一個函數,這個函數能夠是你定義的,也能夠是Python內置函數
(2)第二部分是一個可變參數,*args,好比內置函數max的參數就是一個可變參數,max(1,2,3,4,5)=5
(3)第三部分是一個關鍵字參數,好比內置函數int的第二個參數就是命名關鍵字參數,默認base=10,表示int轉換時默認是10進制的:
partial函數的做用就是:將所做用的函數做爲partial()函數的第一個參數,原函數的各個參數依次做爲partial()函數的後續參數,原函數有關鍵字參數的必定要帶上關鍵字,沒有的話,按原有參數順序進行補充。
文字描述顯得有些無力,咱們下面就開始講一下,偏函數是怎麼用的
2、偏函數的使用
A、偏函數的第二個部分(可變參數),按原有函數的參數順序進行補充,參數將做用在原函數上,最後偏函數返回一個新函數(相似於,裝飾器decorator,對於函數進行二次包裝,產生特殊效果;但又不一樣於裝飾器,偏函數產生了一個新函數,而裝飾器,可改變被裝飾函數的函數入口地址也能夠不影響原函數)
案例:咱們定義一個sum函數,參數爲*args可變,計算這些可變參數的和。
擴展:咱們想要對sum函數求和後的結果,再加上10加上20甚至加更多,獲得一個新的結果
實現:咱們分別用decorator和partial來實現,對比一下兩者的區別
(一)裝飾器 decorator 實現
咱們上一篇,剛剛學過decorator,因此這裏,咱們直接看demo,應該會以爲很容易上手和理解:
test.py
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
from functools import wraps
def sum_add(*args1): #咱們要給咱們的裝飾器decorator,帶上參數
def decorator(func):
@wraps(func) #加上這句,原函數func被decorator做用後,函數性質不變
def my_sum(*args2): #注意,參數要和原函數保持一致,真正實行擴展功能的是外層的裝飾器
my_s = 0
for n in args1:
my_s = my_s +n #這個是咱們新加的求和結果
return func(*args2) + my_s #這個,咱們在原求和函數的結果上再加上s,並返回這個值
return my_sum #返回my_sum函數,該函數擴展原函數的功能
return decorator #返回咱們的裝飾器
@sum_add(10,20) #啓用裝飾器 對sum函數進行功能擴展
def sum(*args):
s = 0
for n in args:
s = s+n
return s
print(sum(1,2,3,4,5))
print(sum.__name__)
sum(1,2,3,4,5)返回的結果毫不是15,這樣就失去了裝飾器存在的意義,固然,這裏,咱們知道,sum最後返回的值應該是10+20+15 = 45,這樣一來,咱們的decorator就實現了咱們想要的擴展功能,最後,發現,原函數sum的name屬性,仍然是sum,說明,這種裝飾擴展功能,不影響咱們的原函數:
(二)偏函數 partial function 實現
這纔是咱們本篇的重點,準備好了,咱們就開始:
咱們先來看下普通函數,咱們是怎麼來實現
A:普通函數可變參數順序執行
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
def sum(*args):
s = 0
for n in args:
s = s + n
return s
print(sum(10,20)+sum(1,2,3,4,5))
咱們若是想實現+10+20的效果,必須寫兩遍sum,這樣寫,顯然是最易懂的,可是,卻顯得很邋遢不專業,咱們看下結果:
B:普通函數可變參數加關鍵字參數組合
針對上面的A過程,咱們改下代碼,使咱們的代碼看起來稍顯複雜,可是略顯專業:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
def sum(*args,**others):
s = 0
for n in args:
s = s + n
s1 = 0
for k in others:
s1 = s1 + others[k] #咱們還要算一下,關鍵字參數裏蘊藏的求和結果,k是dict中的關鍵字key
return s+s1 #最終,咱們實現擴展功能,順序參數和關鍵字參數結果相加
D= {'value1':10,'value2':20}
print(sum(1,2,3,4,5,**D))
代碼看起來,是顯得專業了,可是感受冗餘,不必,複雜不是咱們Python的風格,咱們看下B的結果:
C:偏函數可變參數順序填充一步到位
上面A和B咱們都說過了,這兩種方式都很差,顯然,這麼簡單的事情,咱們沒必要麻煩decorator了,那咱們還有辦法沒?有,Python,給咱們提供了偏函數,來吧,主角登場:
提示:兩種使用partial功能方式
(1)import functools -->functools.partial(func,*args)
(2)from functools import partial -->partial(func,*args)
咱們這裏選第二種,咱們看下demo:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
from functools import partial
def sum(*args):
s = 0
for n in args:
s = s + n
return s
sum_add_10 = partial(sum,10) #10 做用在sum第一個參數的位置
sum_add_10_20 = partial(sum,10,20) #10 20 分別做用在sum第一個和第二個參數的位置
print('A____________咱們看下原函數sum的函數地址入口:')
print(sum)
print('B______咱們看下partial函數返回函數的地址入口:')
print(partial(sum,10))
print(sum_add_10(1,2,3,4,5)) # --> 10 + 1 + 2 + 3 + 4 + 5 = 25
print(sum_add_10_20(1,2,3,4,5)) # --> 10 + 20 + 1 + 2 + 3 + 4 + 5 = 45
上面,能夠看出,咱們針對sum函數的求和結果,再加上10,或者加10加20,甚至加更多,都是能夠經過偏函數來實現的,注意偏函數的第二部分,參數是可變的,是按順序走的,所以,偏函數產生的新函數,sum_add_10 實際上等同於sum(10,*args):
經過幾個例子,咱們最終發現,仍是偏函數比較方便,一行代碼就搞定了,並且新定義的函數,能夠根據函數名很容易知道,這個函數擴展的原函數是哪一個,實現的效果是什麼:
B、偏函數的第三個部分(關鍵字參數),按原有函數的關鍵字參數進行填補,參數將做用在原函數上,最後偏函數返回一個新函數
案例:咱們定義一個mod求餘函數,兩個參數,一個是被除數,一個是除數,除數咱們這裏用命名關鍵字參數表示,默認值2
擴展:咱們的除數不固定,能夠是對2就行求餘,也能夠對3,對4,總之咱們須要指定除數的值
返回結果: True 或 False
實現:原函數實現和partial函數實現
demo以下:
# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
import functools
def mod(m,*,key=2):
return m % key == 0
mod_to_2 = functools.partial(mod,key=2)
print('A__3___使用原函數的默認關鍵字參數對2進行求餘:')
print(mod(3)) #對2進行求餘-- 原函數 使用默認參數
print('B__3___使用偏函數對2進行求餘:')
print(mod_to_2(3)) #對2進行求餘-- 新函數 --偏函數產生
mod_to_5 = functools.partial(mod,key=5)
print('C__25___使用原函數的關鍵字參數對5進行求餘:')
print(mod(25,key=5)) #對5進行求餘 -- 原函數
print('D__25___使用偏函數對5進行求餘:')
print(mod_to_5(25)) #對5進行求餘 -- 新函數--偏函數產生
咱們看下結果:
咱們發現,實際上,偏函數的做用,其實和原函數差很少,只不過,咱們要屢次調用原函數的時候,有些參數,咱們須要屢次手動的去提供值,好比上述的對5進行求餘,若是咱們想知道,15,45,30這些數是否可以被5整除,那麼,咱們用原函數的話,就須要寫三次,key=5,然而,咱們用偏函數的話,只須要重複調用新產生的函數mod_to_5(15 or 45 or 30)便可,至於除數5,偏函數已經爲咱們設定了,所以:
當函數的參數個數太多,須要簡化時,使用 functools.partial 能夠建立一個新的函數,這個新函數能夠固定住原函數的部分參數,從而在調用時更簡單。固然,decorator也能夠實現,若是,咱們不嫌麻煩的話。
結束語:
一種方案行不通的話,咱們就換另外一種方案,若是兩種方案都行得通的話,咱們確保那個最簡單高效的方案,這樣一來,最後受益的將是咱們本身。
d_to_5(15 or 45 or 30)便可,至於除數5,偏函數已經爲咱們設定了,所以:
當函數的參數個數太多,須要簡化時,使用 functools.partial 能夠建立一個新的函數,這個新函數能夠固定住原函數的部分參數,從而在調用時更簡單。固然,decorator也能夠實現,若是,咱們不嫌麻煩的話。
結束語:
一種方案行不通的話,咱們就換另外一種方案,若是兩種方案都行得通的話,咱們確保那個最簡單高效的方案,這樣一來,最後受益的將是咱們本身。