デコレータ関数の基本的なの使い方
デコレータとは、デザインパターンの一種で、クラスの構造を変えずに処理を追加をしたい場合に利用する。Pythonの場合、@関数名として、デコレータを利用できる
- デコレータ(@)を利用しない例(内部関数についてはこちら)
def wrapper():
print("print before func")
func() # 引数に渡された関数を実行
print("print after func")
return wrapper
def say_hi():
print("hi!")
say_hi = my_decorator(say_hi) # 関数say_hiを渡す
say_hi() # 実行する(my_decorator(say_hi)→wrapper(funcにsay_hiが入る))
- デコレータ(@)を利用した例
def wrapper():
print("print before func")
func()
print("print after func")
return wrapper
@my_decorator
def say_hi():
print("hi!")
# my_decorator(say_hi)の返り値としてsay_hiが定義される
say_hi() # デコレータを利用しない例と同じように実行される
他にも色んなデコレータの利用方法を記述する
- デコレータを使って、処理の前と後にstartとendを表示する方法
def wrapper():
print("start")
func()
print("end")
return wrapper
@add_start_end
def a():
# プログラム
@add_start_end
def b():
# プログラム
a() # a = add_start_end(a)、aの中のプログラムの前と後に、startとendが表示される
b() # b = add_start_end(b)、bの中のプログラムの前と後に、startとendが表示される
- デコレータを使って、処理を2回実行する方法
def wrapper():
func()
func()
return wrapper
@do_twice
def a():
#プログラム
@do_twice
def b():
#プログラム
デコレータ関数の応用的なの使い方1(複数のデコレータ、引数を付けた呼び出し)
また、デコレータ関数には、応用的な使い方もある。
以下に記述する
- デコレータに返り値を持たせる
返り値を持たせるには、wrapperの関数内にreturnを記述する
def wrapper():
str = f"str = {func()}"
return str
return wrapper
@decorator
def a():
return "A"
# @decoratorを用いると、a=decorator(a)となり、a()を実行すると"str = A"が返される
print(a()) str = A
- デコレータに引数を持たせる
def wrapper(str): # 引数を持たせる
print("*" * 10)
func(str) # funcを引数と共に呼び出し
print("*" * 10)
return wrapper
@add_decoration
def a(str): # 引数を持たせる
print(str)
a("Hello World") # 引数付きで実行
#以下のように表示される
#**********
#Hello World
#**********
デコレータ関数の応用的なの使い方2(複数のデコレータ、引数を付けた呼び出し)
デコレータは以下のように複数宣言することもできる。
@decorator1
@decorator2
def function():
この場合、pythonの内部的には、以下のように解釈される
function = decorator1(decorator2(function))
- 複数のデコレータを用いる
def wrapper():
func()
func()
return wrapper
def add_decoration(func):
def wrapper():
print("*" * 10)
func()
print("*" * 10)
return wrapper
@add_decoration
@do_twice
def print_helloworld():
print("hello world")
print_helloworld()
# print_helloworldはdo_twice(add_decoration(print_helloworld))になります。
# do_twiceでprint_helloworldを2回実行し、add_decorationで*を"hello world"の前後につけます
#出力結果
#**********
#hello world
#hello world
#**********
デコレータの引数を付ける場合はシンプルに@decorator("")と記述する。
以下関数
@decorator("something")
def a():
は
a = decorator("something")(a)
のように解釈され、decorator("something")の戻り値の関数に、関数aが引数として割り当てられる
一般的には、デコレータに引数を渡す場合、デコレータ関数は、内部関数を2重に記述する。
- デコレータを引数付きで渡す
def wrapper1(func):
def wrapper2():
print(message)
func()
print(message)
return wrapper2
return wrapper1
@add_message("I love python")
def print_helloworld():
print("hello world")
print_helloworld()
# を実行した結果、以下のように表示される
#I love python
#hello world
#I love python