💡

Pythonにおけるラッパー関数のテクニック:functools.wraps

2023/03/29に公開

結論

ラッパー関数作成時はfunctools.wrapsを使う!!

通常のラッパー関数と弊害

ラッパー関数とは、元の関数を書き換えることなく、機能を追加する関数である。

ラッパー関数は例えば以下のように書く。

def trace(func):
    def wrapper(*args,**kwargs):
        result = func(*args,**kwargs)
        print('Hello') #追加したい処理
	return result
    return wrapper
@trace 
def f(n):
    """nの2乗を返す関数"""
    return n**2 #元の処理

これでもラッパー関数として機能するが、fを呼び出すと以下のように出力される。

<function __main__.trace.<locals>.wrapper(*args, **kwargs)>

このように出力されると、wrapperを用いていることはわかるが、肝心のf自体が何か判別できない。

pickledumpでもシリアライズできず、デバックも困難になってしまうので改善が必要である。

functools.wrapsを用いた改善

ラッパー関数を使用しても、関数fが何かわかるようにするには、以下のようにwrapsを用いてラッパー関数を定義すると良い。

from functools import wraps
def trace(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        result = func(*args,**kwargs)
        print('Hello') #追加したい処理
	return result
    return wrapper
    
@trace 
def f(n):
    """nの2乗を返す関数"""
    return n**2 #元の処理

from functools import wrapsはラップする関数の情報(内部関数の情報)を外部関数に複製する役割を持つ。

つまりfを(外部から)呼び出したとしてもfの中身の情報を参照することができる。

このように定義したfを呼び出すと以下の結果が得られる。

<function __main__.f(n)>

fの中身を把握するにはhelp関数を用いればよい。
help関数の結果が以下であり、Docstringの内容を出力できる。

Help on function f in module __main__:

f(n)
    nの2乗を返す関数

ラッパー関数の実例

ラッパー関数の実例は過去こちらで紹介している。

https://zenn.dev/sergicalsix/articles/6434552139b126

Discussion