Python decoratorの簡単な練習1

decorator(デコレーター)が今一つ分かっていないので簡単な練習。

絵はdecoraotor => decorate => decoration => デコレーションケーキと言う事で。

まずは普通の関数を使ったファイルsample0.pyを作る

def printscript():
    print("Hello world")

printscript()

これを実行すると

% python3 sample0.py
Hello world

これはいつも通り。

これにまずはprint内容を書き換える為のdecoratorを追加。
書き換えたいfunction、deco(func)を書き、書き換えたい先のfunctionの上に@decoと付ける。
deco(func)はdeco(func)の中の関数wrapperを返す(return)ので、それがprintscript()の出力になる。

def deco(func): # decorator関数の宣言、funcにはfunction printscript()が引数として与えられる
    def wrapper(*args, **kwargs): # デコレーターの中身、*args, **kwargsはデコレートする関数の引数。幾つあっても大丈夫な書き方。
        print("Good evening world")
    return wrapper

@deco
def printscript():
    print("Hello world")

printscript()

出力がHello worldでは無く、decoratorで書き換えられたGood evening worldになっているのが分かる。

% python3 Sample0.py
Good evening world

次はプリント文を飾ってみたい。
下記をsample01.pyとして保存、実行。

def deco(func): # decorator関数の宣言、funcにはfunction printscript()が引数として与えられる
    def wrapper(*args, **kwargs): # デコレーターの中身、*args, **kwargsはデコレートする関数の引数。幾つあっても大丈夫な書き方。
        print('*'*len("Hello world"))
        func(*args, **kwargs) # 引数として渡された関数(printscript)を実行
        print('*'*len("Hello world"))
    return wrapper

@deco
def printscript():
    print("Hello world")

printscript()

@decoでデコレートする名前の関数deco(func):を設定、このfuncにはデコレートした関数printscriptが引数として与えられる。

中の関数def wrapper(*args, **kwargs):のfunc(*args, **kwargs)でこの引数の関数(printscript)を実行。

今回はこの前後でHello worldと同じ長さの”*”を出力して挟み込むデコレートをする。
正に修飾。

最後にreturnで値を返し、この値が関数printscript()に返された事で、下記の通り出力される。

% python3 sample1.py
***********
Hello world
***********

このdecorator, 一旦設定すると色々な関数に使える。

こちらをsample1fl.pyとして保存する。

def deco(func): # decorator関数の宣言、funcにはfunction printscript()が引数として与えられる
    def wrapper(*args, **kwargs): # デコレーターの中身、*args, **kwargsはデコレートする関数の引数。幾つあっても大丈夫な書き方。
        print('*'*len("Hello world"))
        func(*args, **kwargs) # 引数として渡された関数(printscript)を実行
        print('*'*len("Hello world"))
    return wrapper

@deco
def printscript():
    print("Hello world")

printscript()

@deco
def forloop():
    for i in [1, 2, 3, 4, 5]:
        print(i)

forloop()

デコレータは同じモノを使っているが、所与のリスト1〜5の数字を順次出力する関数forloop()を追加した。

printscript()は同じ出力だが、forloop()はどの様に出力するだろうか。
一つ一つにデコレートされるのだろうか?

% python3 sample1fl.py
***********
Hello world
***********
***********
1
2
3
4
5
***********

最初と最後だけにデコレートした行が追加された。
なる程、decoratorは関数forloop()全体をデコレートすると言う理解。

11/10追記:pythonファイルの実行と出力結果のソースコードについて、Visual Studioでの出力結果を記載していた為にターミナル表記と異なっていた点を修正しました。

“Python decoratorの簡単な練習1” への3件の返信

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

13 − 11 =

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください