python的partial()用法說明

駿馬金龍發表於2018-12-29

在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()也很少用。

相關文章