1、引言
Python作為一種強類型動態語言,擁有豐富的函數式編程特性。其中一個特點是支持偏函數——partial函數。這恰好可以解決我們常常遇到的「非固定參數」問題。關於這個,我們先從一個例子入手:
def power(x, y): return x**y print(power(2, 3)) # 輸出8 print(power(2, 4)) # 輸出16
在這個例子中,我們定義了一個求冪的函數,但是某一次我們需要默認計算2的平方,這種情況下我們可以直接調用 power(2, 2)
。這時候,如果你的代碼里有大量這個樣子的情況,你肯定不想在每個函數里都寫 2, 2
。
那麼我們怎麼辦呢?
這時候就需要partial函數了。
2、partial函數的基本用法
1) partial函數的起源
我們有這麼一個場景:我們需要對一個列表裡所有的數字進行乘以2,然後再加1的操作,得到新的列表。
lst = [0, 1, 2, 3] new_lst = [(x * 2 + 1) for x in lst] print(new_lst) # 輸出[1, 3, 5, 7]
在上面的例子中,我們不僅寫起來很麻煩,而且還寫出了一堆冗長的代碼,難以維護。這時候我們需要partial函數的出現。
2) partial函數的定義
Python的functools模塊提供了一個叫做partial的函數,它可以幫助我們創建偏函數。那麼,什麼是偏函數呢?
偏函數是函數式編程中的一個概念,它可以把一個函數的某些參數給固定住,返回一個新的函數,簡化原函數的調用。在調用新函數的時候,只需要傳入未曾固定的參數即可。
為了更好地理解,我們下面通過一些例子來逐步探究partial函數的用法。
3) partial函數的第一個例子
實際上,在第一個例子中,我們已經使用了類似偏函數的思想。題目要求我們對a列表中的所有數乘以3,所以我們寫出了下面的代碼:
a = [1, 2, 3, 4, 5] b = list(map(lambda x: x * 3, a)) print(b) # 輸出[3, 6, 9, 12, 15]
在使用lambda表達式的時候,我們把x * 3
作為參數傳給了map()函數,使用了函數式編程的思想。
而使用partial函數,我們就可以使用更為簡潔的方式把參數固定下來:
from functools import partial def multiply(a, b): return a * b times_three = partial(multiply, b=3) print(times_three(2)) # 輸出6
在上面的例子中,我們把multiply函數中的b參數固定為3,得到了一個新函數times_three。我們後續只需要傳入a參數即可。
4) partial函數的第二個例子
接下來,我們將繼續了解partial函數的應用。我們再來看一個例子。假設有一個函數:
def calculate(a, b, c, d): return a + b + c - d
我們現在需要調用一個函數,它的第一個參數是5,剩餘的參數是calculate()函數的剩餘參數。
如果我們使用標準的調用,代碼會變得非常冗長:
calculate_params = (6, 7, 8) result = calculate(5, *calculate_params, 2) print(result) # 輸出24
這裡,我們原本需要傳遞5,6,7,8和2這幾個參數。但是,為了讓代碼的可讀性更高,我們嘗試使用partial函數,重構代碼:
calculate_params = (6, 7, 8) partial_calculate = partial(calculate, 5, *calculate_params) result = partial_calculate(2) print(result) # 輸出24
在上面的例子中,我們利用了partial函數把calculate()函數中前兩個參數的值固定為5和6。
由此,我們可以看到,partial函數可以大大提高我們代碼的可讀性,使得代碼更加簡潔和易於維護。接下來,我們將介紹partial函數的高級用法。
3、partial函數的高級用法
1) 通過partial函數改變函數的行為
在實際應用中,有時候我們需要使用partial函數來改變原函數的行為,可以實現更加多樣化的功能。
我們通過一個例子來說明這種用法:
from functools import partial def calculate(a, b, c, d): return a + b + c - d difference = partial(calculate, d=0) # 固定d參數為0 print(calculate(1, 2, 3, 4)) # 輸出2 print(difference(1, 2, 3)) # 輸出6
在上面的例子中,我們調用了partial函數,把calculate()函數中的d參數固定為0。
但是如果我們願意,我們還可以把這個新的函數的參數再一次固定住,例如:
difference = partial(calculate, b=2, d=0) print(difference(1, 3)) # 輸出6
在這個例子中,我們把calculate()函數中的b和d參數均固定為特定的值,得到了一個新的函數difference。我們可以僅傳遞2個參數調用它,而不用考慮其他參數的值。
2) 通過partial函數改變函數簽名
有些時候,我們需要改變函數簽名,以達到某種目的。在Python中,我們可以使用partial函數完成這種需求。
下面,我們來看一個例子,它能夠幫助我們更好地理解partial函數如何改變函數簽名:
from functools import partial def calculate(a, b=0, c=0, *, d=1, e=1): return a + b + c - d + e new_calculate = partial(calculate, e=2) print(new_calculate(1, 2)) # 輸出2
在上面的例子中,我們調用了partial函數,並且把e參數固定為2。此時,新的函數new_calculate()的簽名變成了:
signature(new_calculate) # 輸出inspect.Signature(parameters=[, , , ])
由此,我們可以看出, partial函數可以改變函數的參數簽名,以實現更加靈活的功能。
3) 將可調用對象轉換為函數
有的時候,可能需要將一個自定義的可調用對象轉換為函數對象,以方便使用。在Python中我們可以使用partial函數來實現這一目的。
簡單來說,如果一個對象不是一個函數對象,那麼partial函數可以將其轉換成函數對象。在這種情況下,這個對象被看作是一個調用對象,它可以調用,但是不具備函數的特性。這時候,我們需要藉助partial函數幫助我們實現高級特性。
接下來,我們通過一個例子探究如何把可調用對象轉換成函數對象。
from functools import partial class Operations: def __init__(self, a, b): self.a = a self.b = b def add(self): return self.a + self.b def mul(self): return self.a * self.b op = Operations(5, 6) print(op.add()) # 輸出11 print(op.mul()) # 輸出30 add_op = partial(op.add) # 轉換成函數 print(add_op()) # 輸出11
在上面的例子中,我們定義了一個Operations類,並且為其添加了add和mul兩個方法。
接下來,我們使用partial函數把其中一個方法轉換成函數,並且實現了調用,成功得到了輸出結果。
4、結論
總的來說,Python中的partial函數是一個十分有用的工具,它可以提高我們編寫代碼的可讀性和代碼的維護性。
partial函數有豐富的用法,可以通過對參數進行固定,讓我們的代碼更加簡潔;也可以改變函數的簽名以支持更高級的特性;還可以把可調用對象轉換成函數對象以方便使用。
在實際工作中,我們可以結合實際的應用需求,充分了解partial函數的用法,發揮其巨大的價值和作用。希望本文可以幫助大家更好地了解partial函數的用法和應用場景。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/257144.html