end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

pythonのdecoratorやcontextlibによる前後への処理追加

先程のentryに関連?として、以下のqiitaからの写経です。

https://qiita.com/chocomintkusoyaro/items/214f87a6300a88d15363

# cf. https://qiita.com/chocomintkusoyaro/items/214f87a6300a88d15363
import contextlib
import sys

def main():
    msg = "this is test message"
    decorated_1( msg )
    decorated_2( msg )
    decorated_3( msg )
    decorated_4( msg )

def decorator_1(org_func):
    func_name = sys._getframe().f_code.co_name
    
    def wrapper(content):
        print(func_name,"start")
        result = org_func(content)
        print(func_name,"goal")
        return result
    return wrapper

@decorator_1
def decorated_1(content):
    print(content)

#### decoratorに引数を渡す場合。ソースが分かりづらいですが
def decorator_2(name):
    def sub_decorator(org_func):
        def wrapper(content):
            print(name,"start")
            result = org_func(content)
            print(name,"goal")
            return result

        return wrapper
    return sub_decorator

@decorator_2('deco2')
def decorated_2(content):
    print(content)
    
    
#### decorator_2の別の書き方。
@contextlib.contextmanager
def decorator_3(name):
    print("{} start".format(name))
    yield  ## 処理の一時停止
    print('{} end'.format(name))

def decorated_3(content):
    func_name = sys._getframe().f_code.co_name
    
    with decorator_3( func_name):
        print(content)


#### decorator_3の更に別の書き方。
class decorator_4(contextlib.ContextDecorator):
    def __init__(self, name):
        self.name = name
        self.start_tag = '<{}>'.format(name)
        self.end_tag = '</{}>'.format(name)

    # デコレーションに入ったときの動作を定義
    def __enter__(self):
        print(self.start_tag)

    # デコレーションを抜けるときの動作を定義
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(self.end_tag)

def decorated_4(content):
    with decorator_4('decorated'):
        print( content )
    
if __name__ == '__main__':
    main()

↑こう書くと、↓こう表示されます

>python foo.py
decorator_1 start
this is test message
decorator_1 goal
deco2 start
this is test message
deco2 goal
decorated_3 start
this is test message
decorated_3 end
<decorated>
this is test message
</decorated>