0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python初心者】@functools.wraps の役割をやさしく理解する(カスタムデコレーターでの使い方)

0
Posted at

前回、Pythonのカスタムデコレーターについて学びました。
今回はその続きとして、@functools.wraps というデコレーターの中でよく使われる仕組みについて、自分なりに整理してみます。

まだデコレーターの仕組み自体がよく分からない方は、先にそちらを確認すると分かりやすいと思います。

どうして wraps が必要なの?

まずは何もつけずにカスタムデコレーターを使った場合の例です。

def my_decorator(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def greet():
    """挨拶をする関数"""
    print("こんにちは!")

print(greet.__name__)
print(greet.__doc__)

実行結果:

wrapper
None

なぜこうなるの?

  • @my_decorator によって、greet の中身が wrapper に置き換わる
  • その結果、__name____doc__wrapper のものになってしまう

関数の名前や説明(ドキュメント文字列)が上書きされてしまうのは、後から関数を調べたり、ツールで扱ったりするときに困ることがあります。

functools.wraps で解決できる!

そこで出てくるのが functools.wraps です。
これは元の関数の情報(名前・docstringなど)を保持するための「補助的なデコレーター」です。

from functools import wraps

def my_decorator(func):
    @wraps(func)  # ← これを追加するだけ
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def greet():
    """挨拶をする関数"""
    print("こんにちは!")

print(greet.__name__)
print(greet.__doc__)

実行結果:

greet
挨拶をする関数

今度はちゃんと greet という名前と docstring が保持されています!

まとめ:wraps の役割とポイント

項目 内容
機能 元の関数の情報(__name__, __doc__ など)をラッパー関数にコピーする
使用場所 デコレーター内の wrapper 関数に @wraps(func) をつける
必須か? デコレーターの機能には関係ないが、ベストプラクティスとして使うべき
インポート方法 from functools import wraps

おわりに

@wraps は、デコレーターを使うときによく一緒に見かけるものですが、最初は「なんでこれがいるの?」とよく分かりませんでした。

ですが実際に __name____doc__ が失われる例を見てみると、「これはあったほうがいいな」と納得できました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?