ソフトな忘却力(114) Pythonのfunctoolsでラッピングとな?

Joseph Halfmoon

「サイエンティフィックPythonのための」IDE、Spyder上にてScientific Python Lecturesの実習中。今回はラッピング?です。単純なデコレータでオブジェクトを「書き替えて」しまうと、元のオブジェクトのお名前や文書属性が失われてしまうみたい。そこでfunctoolsでデコレータをラッピング?

※「 ソフトな忘却力」投稿順 Index はこちら

※今回からSypder IDEをWindows版 6.0.7に変えました。使い方は変らんと思います。なお使用のPython処理系はPython 3.11.12です。

Scientific Python Lectures様のコースは例題だけでなく、エクササイズなども充実、それを全部順番に解いていったら必ずや立派な人になれるだろ~と思います。でも老い先短い年寄には量が多過ぎて多分死ぬまでに終わりません。適当な練習でお茶を濁してます。今回は「7.2 Decorators」の「7.2.3 Copying the docstring and other attributes of the original function」です。

「素」のデコレータでラップすると「見えなくなる」のね

以下のようにフツーに関数を定義してみます。
functionA_nowrapper

すると上記のように属性 __doc__、__name__などに値が設定されていることが分かります。これを手がかりにあれやこれやできるんだと。

一方、前々回、関数をデコレータで「ラップ」して新たなオブジェクトを返しました。そのときのデコレータの定義は以下のようでした。decoratorSample

上記のようなデコレータを用いて関数を「デコレーション」してみると以下のようです。functionA_wrapper

あちゃ~、関数のお名前 __name__属性は wrapper になっているし、__doc__属性は空だと。ううむ、ラッパとして返ってきたオブジェクトはデコレータ定義の中のwrapper関数で、functionAではないからでしょうな。しかたがない?

functools

しかたない、などといいつつ、Pythonの中の人には抜かりが無いのでした。以下を御覧じろ。

functools — 高階関数と呼び出し可能オブジェクトの操作

元のオブジェクトの属性どもを、返されるラッパ関数の属性としてコピーしてから戻せるテクがあるみたい。

レクチャの中では、functools.update_wrapper()を直接呼び出してましたが、上記のドキュメントみると便宜関数 wrapsというものも定義されており、これをつかうと「デコレータ表記」(デコレータがネストすることになる)でカッコよくかけるみたい。こんな感じ。

functools_wrap

おお、デコレータの威力よな。簡潔な記述。

するとどうでしょう、functionA_wrapper_wrap

デコレータで書き替えられた元関数の属性がちゃんと「引き継がれ」ているように見えます。やったね。

ソフトな忘却力(113) PythonのDecorator「クラス」で関数を修飾 へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です