Python3學習(18)--偏函式(Partial)
轉自:https://blog.csdn.net/appleyk/article/details/77609114
一、什麼是偏函式?
(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()函式的後續引數,原函式有關鍵字引數的一定要帶上關鍵字,沒有的話,按原有引數順序進行補充。
文字描述顯得有些無力,我們下面就開始講一下,偏函式是怎麼用的
二、偏函式的使用
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也可以實現,如果,我們不嫌麻煩的話。
結束語:
一種方案行不通的話,我們就換另一種方案,如果兩種方案都行得通的話,我們確保那個最簡單高效的方案,這樣一來,最後受益的將是我們自己。
相關文章
- python的偏函式(partial)Python函式
- python進階(17)偏函式partialPython函式
- python 中偏函式 partial 的使用Python函式
- Python利用partial偏函式生成不同的聚合函式Python函式
- Python3基礎-特別函式(map filter partial reduces sorted)例項學習Python函式Filter
- JavaScript 偏函式JavaScript函式
- 927|偏函式函式
- Scala偏函式函式
- 函式式點滴--partial&curry函式
- 函式柯里化和偏函式應用函式
- JavaScript 專題之偏函式JavaScript函式
- 函式學習函式
- 【Mysql 學習】日期函式函式MySql函式
- python3 的 round 函式的 練習Python函式
- 笨辦法學C 練習18:函式指標函式指標
- spark RDD的學習,filter函式的學習,split函式的學習SparkFilter函式
- MySQL函式學習(一)-----字串函式MySql函式字串
- 測開之函式進階· 第5篇《偏函式》函式
- 函式學習五函式
- 函式學習六函式
- 函式學習三函式
- 函式學習四函式
- 函式學習二函式
- 函式的學習函式
- 學習Rust 函式Rust函式
- 學習dump函式函式
- ORACLE函式學習Oracle函式
- Solidity語言學習筆記————18、字串和函式Solid筆記字串函式
- python函式程式設計 返回函式 匿名函式 裝飾器 偏函式Python函式程式設計
- Python 偏函式用法全方位解析Python函式
- 字串函式學習三字串函式
- 字串函式學習一字串函式
- 字串函式學習二字串函式
- TypeScript學習(二)—— 函式TypeScript函式
- js學習二函式JS函式
- 【Mysql 學習】流程函式MySql函式
- 分析函式的學習函式
- numpy學習回顧-數學函式及邏輯函式函式