在functools模塊中有一個工具partial(),可以用來"凍結"一個函數的參數,並返回"凍結"參數後的新函數。 很簡單的解釋,也是 "官方手冊" 給的示例。對於int()函數,它可以將給定的數值轉換成十進位整數,轉換時可以指定以幾進位的方式解析給定的數。例如: 現在不想這樣指定 參數來將二進 ...
在functools模塊中有一個工具partial(),可以用來"凍結"一個函數的參數,並返回"凍結"參數後的新函數。
很簡單的解釋,也是官方手冊給的示例。對於int()函數,它可以將給定的數值轉換成十進位整數,轉換時可以指定以幾進位的方式解析給定的數。例如:
# 以10進位解析123,並轉換成10進位整數
>>> int("123")
123
# 以2進位解析10101,並轉換成10進位整數
>>> int("10101", base=2)
21
# 以13進位解析"abc12c",並轉換成10進位整數
>>> int("abc12c", base=13)
4053672
現在不想這樣指定base=2
參數來將二進位轉換為10進位整數了,而是像普通函數一樣,直接指定待轉換的值即可。於是,定義另外一個函數來封裝int(),例如:
def inttwo(x):
return int(x, base=2)
inttwo("10101")
functools中提供的partial()就是做類似事情的:
inttwo = partial(int, base=2)
它表示int()中指定參數base=2,也就是"凍結"了這個參數。
>>> from functools import partial
>>> inttwo = partial(int,base=2)
>>> inttwo("10101")
21
之所以"凍結"加上了引號,是因為可以在inttwo()中再次指定參數來覆蓋partial()中"凍結"的參數:
>>> inttwo("10101",base=10)
10101
回頭再看partial()的定義:
functools.partial(func, *args, **keywords)
從它的定義不難知道,不僅僅是像int()中base這樣的kw參數格式,位置參數args也一樣能"凍結"。
partial()返回的其實是一個partial對象,這個對象包含了3個特殊的屬性:
>>> dir(inttwo)
[...... 'args', 'func', 'keywords']
func
表示該對象所封裝的原始函數
args
表示"凍結"的位置參數列表
keywords
表示"凍結"的關鍵字參數
>>> inttwo.func
<class 'int'>
>>> inttwo.args
()
>>> inttwo.keywords
{'base': 2}
另外需要註意的是,partial()不會保留封裝函數的元數據,比如註釋文檔、註解等。
>>> def myfunc(x:int, y:int) -> int:
... ''' sum x + y '''
... return x + y
# 函數元數據信息
>>> myfunc.__doc__
' sum x + y '
>>> myfunc.__annotations__
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
# partial()包裝後的函數,沒有函數元數據
>>> newfunc = functools.partial(myfunc,y=3)
所以如果需要這些元數據,必須自己手動將元數據賦值給partial對象:
>>> newfunc.__doc__ = myfunc.__doc__
>>> newfunc.__annotations__ = myfunc.__annotations__
>>> newfunc.__doc__
' sum x + y '
>>> newfunc.__annotations__
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
最後,除了partial()可以將函數的參數"凍結",functools還提供了partialmethod()將方法的參數"凍結",但基本上用不上,就連partial()也很少用。