LoginSignup
0
0

More than 3 years have passed since last update.

【Udemy Python3入門+応用】 57. デコレーター

Posted at

※この記事はUdemyの
現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル
の講座を受講した上での、自分用の授業ノートです。
講師の酒井潤さんから許可をいただいた上で公開しています。

■デコレーターの基本

◆デコレーターを使わずに書くと
non_decorator
def add_num(a, b):
    return a + b

print('start')
r = add_num(10, 20)
print('end')

print(r)
result
start
end
30

add_num() を呼び出すだけでなく、その前後などでなにか追加で行いたいとき、「デコレーター」を用いることができる。

◆デコレーターを使って書くと
decorator
def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

def add_num(a, b):
    return a + b

f = print_info(add_num)
r = f(10, 20)
print(r)
result
start
end
30

*args については、52. 位置引数のタプル化
**kwargs については53. キーワード引数の辞書化 を参照。

◆デコレーターの一般的な使い方

上の様に記述すると、デコレーターとして使っているということがわかりにくい。
なので、一般的にデコレーターを用いるときには以下の様に記述する。

decorator
def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_info
def add_num(a, b):
    return a + b

r = add_num(10, 20)
print(r)
result
start
end
30

@ を使ってデコレーターの関数を指定してやることで、その関数を使ってデコレートできる。

■デコレーターを複数使う場合

◆デコレーターをかける順番

もう1つデコレーターの関数を書いて、2つとも使ってみる。

two_decorators
def print_more(func):
    def wrapper(*args, **kwargs):
        print('func: ', func.__name__)
        print('args: ', args)
        print('kwargs: ', kwargs)
        result = func(*args, **kwargs)
        print('result: ', result)
        return result
    return wrapper

def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_info
@print_more
def add_num(a, b):
    return a + b

r = add_num(10, 20)
print(r)
result
start
func: add_num
args: (10, 20)
kwargs: {}
result: 30
end
30

このようにデコレーターを指定した場合、
print_info の中に print_more が内包されているのがわかる。

今度は2つのデコレーターの順番を入れ替えてみる。

two_decorators
def print_more(func):
    def wrapper(*args, **kwargs):
        print('func: ', func.__name__)
        print('args: ', args)
        print('kwargs: ', kwargs)
        result = func(*args, **kwargs)
        print('result: ', result)
        return result
    return wrapper

def print_info(func):
    def wrapper(*args, **kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_more
@print_info
def add_num(a, b):
    return a + b

r = add_num(10, 20)
print(r)
result
func: add_num
args: (10, 20)
kwargs: {}
start
end
result: 30
30

今度は、print_more の中に print_info が内包されている。

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