potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

Python 3.8 基本的なデコレータサンプル集

2021/3/10:この記事は別のブログで投稿した記事を移動したものです。

Python 3.8用の基本的なデコレータのサンプル集です。デコレータのテスト用に作成したコード一覧でもあります。

関数をそのまま呼び出すデコレータ

def simple_decorator(f):
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper

@simple_decorator
def func1(*args, **kwargs):
    return args, kwargs

print(func1())
print(func1(123))
#((), {})
#((123,), {})

関数の引数をある定数のみにするデコレータ

def const_arg12345_decorator(f):
    def wrapper(*args, **kwargs):
        return f(12345)
    return wrapper

@const_arg12345_decorator
def func1(*args, **kwargs):
    return args, kwargs

print(func1())
print(func1(123))
#((12345,), {})
#((12345,), {})

関数の引数に名前付き引数を設定するデコレータ

def add_named_arg_123_456_decorator(f):
    def wrapper(*args, **kwargs):
        kwargs["123"] = 456
        return f(*args, **kwargs)
    return wrapper

@add_named_arg_123_456_decorator
def func1(*args, **kwargs):
    return args, kwargs

print(func1(12345))
#((12345,), {'123': 456})

関数の引数を文字列型に変換するデコレータ

def args_as_string_decorator(f):
    def wrapper(*args, **kwargs):
        return f(*[str(arg) for arg in args], **{str(kwarg[1]):str(kwarg[0]) for kwarg in kwargs})
    return wrapper

@args_as_string_decorator
def func1(*args, **kwargs):
    return args, kwargs

print(func1())
print(func1(123))
print(func1(123, 456, args=789))
#((), {})
#(('123',), {})
#(('123', '456'), {'r': 'a'})

関数の呼び出し前後にprint関数を呼び出すデコレータ

def print_before_after_decorator(f):
    def wrapper(*args, **kwargs):
        print("before")
        ret = f(*args, **kwargs)
        print("after")
        return ret
    return wrapper

@print_before_after_decorator
def func1(*args, **kwargs):
    print(*args, **kwargs)
    return args, kwargs

print(func1(12345))
#before
#12345
#after
#((12345,), {})

関数の呼び出し回数を数えるデコレータ

def counter_decorator(f):
    counter = 0
    def wrapper(*args, **kwargs):
        nonlocal counter
        kwargs["counter"] = counter
        counter += 1
        return f(*args, **kwargs)
    return wrapper

@counter_decorator
def func1(*args, **kwargs):
    return args, kwargs

@counter_decorator
def func2(*args, **kwargs):
    return args, kwargs

print(func1(12345))
print(func2(12345))
print(func2(12345))
#((12345,), {'counter': 0})
#((12345,), {'counter': 0})
#((12345,), {'counter': 1})

自身の作成を報告するデコレータ

def counter_decorator(f):
    print(f"counter_decorator for {f.__name__}")
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper

@counter_decorator
def func1(*args, **kwargs):
    return args, kwargs

@counter_decorator
def func2(*args, **kwargs):
    return args, kwargs

print(func1(12345))
print("-----")
print(func2(12345))
print(func2(12345))
#counter_decorator for func1
#counter_decorator for func2
#((12345,), {})
#-----
#((12345,), {})
#((12345,), {})