💨

【Python】デコレーターの挙動

2024/09/16に公開

デコレーターの使い方

デコレーターとは?

  • 関数の中で別の関数を呼び出す際に前後に処理を追加したり呼び出す側で定義自体を変更することなく、関数を呼び出せることで関数の動作を拡張できる機能。

@を使用せず手動で適用する場合

def my_decorator(func):
    def wrapper():
      print("start")
      func()
      print("stop")
    return wrapper

def say_hello():
    print("Hello!")

# 手動でデコレーターを適用
say_hello = my_decorator(say_hello)

# デコレーターが適用された関数を呼び出す
say_hello()

result
start
Hello!
stop

@」を使用する場合

イメージ

  • say_hellomy_decoratorでラップして包み込むイメージ。
    具体有的には、my_decoratorsay_helloを引数として受け取り、その内部でラップすることでwrapper関数を作り出す。
def my_decorator(func):
    def wrapper():
      print("start")
      func()
      print("stop")
    return wrapper

# 「@{呼び出す側の関数}」でよしなに適用してくれる。
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
result
start
Hello!
stop

デコレーターを複数の関数へ適用する使い方

def my_decorator(func):
    def wrapper():
        print("start")
        func()
        print("stop")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

@my_decorator
def say_goodbye():
    print("Goodbye!")

@my_decorator
def say_thanks():
    print("Thanks!")

# 関数を呼び出す
say_hello()
say_goodbye()
say_thanks()
result
start
Hello!
stop
start
Goodbye!
stop
start
Thanks!
stop

複数のデコレーターを1つの関数へ適用する場合

  • まず、デコレーターを適用する順序で処理が変わってくる。
    • 上段(上位)のデコレーターのなかに下段(下位)のデコレーターが入り、その中で関数が二重で包み込まれるイメージ。
def my_decorator(func):
    def wrapper():
        print("start")
        func()
        print("stop")
    return wrapper

def my_decorator_2(func):
    def wrapper():
        print("first")
        func()
        print("second")
    return wrapper

@my_decorator
@my_decorator_2
def say_hello():
    print("Hello!")

# 関数を呼び出す
say_hello()
result
start
first
Hello!
second
stop

デコレコレーターの適用順序を変更

def my_decorator(func):
    def wrapper():
        print("start")
        func()
        print("stop")
    return wrapper

def my_decorator_2(func):
    def wrapper():
        print("first")
        func()
        print("second")
    return wrapper

# デコレーターを適用する順序を逆にする場合
@my_decorator_2
@my_decorator
def say_hello():
    print("Hello!")

# 関数を呼び出す
say_hello()
result
first
start
Hello!
stop
second

GitHubで編集を提案

Discussion