functools wraps

Python学習【365日チャレンジ!】303日目のマスターU(@Udemy11)です。

昨日また近くのスーパーで大きなアジが150円で売っていたので、またまた買ってしまいました。

今回は、フライではなく、アジの開きにして一夜干しとみりん干しを作ってみましたが、これまた旨味が凝縮されて美味しかったのですが、ちょっと気になることが。。。

若干目が曇っていたので、新鮮ではないのかなぁとおもいつつ、津本式の血抜きをしてもなかなか血が抜けませんでした。

で、3枚に下ろしてみると、中のほうが凍っている感じがしたので、もしかしたら、前回のセールで売れ残ったのを冷凍してから解凍したアジを販売してるんじゃないの?なんて思ってしまいました。

ま〜美味しかったので、いいんですけど〜。

それでは今日も、Python学習を始めましょう。

昨日の復習

昨日は、cacheを使って処理を高速化するlru_cacheを学習しました。

lru_cacheを使うことで、処理に時間がかかる関数の実行結果を保存しておいて、再利用して処理を高速化することができました。

処理結果をキャッシュに一時的に保存しておくことでサーバーの負担を減らしたり、処理を待つユーザーのストレスを減らしたりすることができるので、キャッシュは、ブラウザーをはじめ、様々なシーンで活用されています。

lru.cacheの使い方については、昨日の記事をごらんください。

今日は、デコレーターを使った時にdocstringの表示を操作できるfunctools.wrapsを学習します。

デコレーターの復習

Pythonのバージョンが上がるたびに便利な機能が追加されてモジュール化されていきますが、functools.wrapsは、デコレータを使った時に、実行関数のドキュメントを表示するためのモジュールです。

まずはデコレーターを復習しましょう。

def d(f):
    def w():
        print('decorator')
        return f()
    return w

@d
def test():
    print('test')

test()

引数fを取る関数dを定義して、その中にdecoratorと出力したあと関数dの引数fを関数として返す関数wを定義して、関数dの返り値をwとするのがデコレーターです。

7行目に関数dをデコレーターにして、testと出力するtest関数を定義しています。

最後の11行目で関数testを実行します。

出力結果

decorator
test

最小限のコードなので、decoratortestが出力されているだけですが、実行する関数の前後に処理をさせることができました。

functools.wraps

先程のかんたんなコードの関数test()にドキュメンテーションを記述して、それを出力しようとしてもデコレーターが関係して、出力することができません。

def d(f):
    def w():
        print('decorator')
        return f()
    return w

@d
def test():
    """test docstring"""
    print('test')

print(test.__doc__)

出力結果

None

関数testに書いたdocstringは、test.__doc__で出力できるはずですが、Noneが返されました。

3行目に"""wrapper docstring"""と記述して、再度実行してみると、wrapper docstringと表示されます。

こんな時に、実行関数のドキュメンテーションを出力できるのが、functools.wrapsです。

これまでに記述したコード1行目にimport functoolsと3行目にfunctools.wrapsを記述することで、デコレーターのdocstringではなく、実行関数のドキュメントに記述してあるtest docstringが出力されるようになります。

まとめ

Python学習の初心者に撮っては、デコレーターがややこしいし、さらにdocstringとなると、あまり興味をそそられないかもしれません。

とはいえ、企業案件などでは細かくdocstringの記述を求められることもあるらしいので、今回学習した内容は、とりあえず頭の片隅に残しておいてください。

ということで、明日もGood Python!