[Python] Decorator 介紹

程式語言:Python
功能:簡化程式,可用在計算程式效率或重新撰寫 function,其實就是 closure

用法:@ + function 名字,使用在欲重新定義的 function 前

兩者意義等同

def logged(func):
    def with_logging(*args, **kwargs):
        return func(*args, **kwargs):
    return with_logging

@logged
def f(x):
   """does some math"""
   return x * x
或者
def f(x):
   """does some math"""
   return x * x

f = logged(f)

流程

  1. 重新初始化 function 並回傳 function 且重新定義之
  2. 直到呼叫 function,才執行重新定義後的 function
  3. 回傳定義後的值

Decorator Function 測試

def logged(func):
    print('entry init enter')
    def with_logging(*args, **kwargs):
        print("Entering", func.__name__)
        print("arg:",*args)
        print("kwarg:",**kwargs)
        result = func(*args, **kwargs)
        print("Exited", func.__name__)
        return result
    print('entry init exit')
    return with_logging
 
print('decorator using')
@logged
def f(x):
   """does some math"""
   return x * x

print('test start')
print(f(3))

輸出結果:
decorator using
entry init enter
entry init exit
test start
Entering f
arg: 3
kwarg:
Exited f
9

Decorator Class 測試

class entryExit(object):

    def __init__(self, f):
        print('entry init enter')
        self.f = f
        print('entry init exit')

    def __call__(self, *args, **kwargs):
        print("Entering", self.f.__name__)
        r = self.f(*args, **kwargs)
        print("Exited", self.f.__name__)
        return r

print('decorator using')

@entryExit
def hello(a):
    print('inside hello')
    return("hello world " + a)

print('test start')
print(hello('friends'))

輸出結果:
decorator using
entry init enter
entry init exit
test start
Entering hello
inside hello
Exited hello
hello world friends

四種寫法

沒有參數的 Decorator Function
def decorateApple(f):
    def d_f(*args, **kargs):
        print("apple before call")
        result = f(*args, **kargs)
        print("apple after call")
        return result
    return d_f

@decorateApple
def print_hello():
    print("hello first time.")

print_hello()

#apple before call
#hello first time.
#apple after call

有參數的 Decorator Function
def decorateFruit(fruit, rotLevel):
    def outer_d_f(f):
        def d_f(*args, **kargs):
            print("%s %s before call" % (rotLevel, fruit))
            result = f(*args, **kargs)
            print("%s %s after call" % (rotLevel, fruit))
            return result
        return d_f
    return outer_d_f

@decorateFruit('banana', 'new')
def print_hello2():
    print("hello 2nd time.")

@decorateFruit('guava', '50% rot')
def print_hello3():
    print("hello 3th time.")

print_hello2()
print('')
print_hello3()

#new banana before call
#hello 2nd time.
#new banana after call
#
#50% rot guava before call
#hello 3th time.
#50% rot guava after call

沒有參數的 Decorator Class
class decorateAppleClass(object):
    def __init__(self, f):
        self.f = f
    
    def __call__(self, *args, **kargs):
        print("apple before call")
        result = self.f(*args, **kargs)
        print("apple after call")
        return result


@decorateAppleClass
def print_hello4():
    print("hello 4th time.")

print_hello4()

#apple before call
#hello 4th time.
#apple after call

有參數的 Decorator Class
class decorateFruitClass(object):
    def __init__(self, fruit, rotLevel):
        self.fruit = fruit
        self.rotLevel = rotLevel

    def __call__(self, f):
        def d_f(*args, **kargs):
            print("%s %s before call" % (self.rotLevel, self.fruit))
            result = f(*args, **kargs)
            print("%s %s after call" % (self.rotLevel, self.fruit))
            return result
        return d_f

@decorateFruitClass('guava', '80% rot')
def print_hello5():
    print("hello 5th times.")

@decorateFruitClass('banana', '30% rot')
def print_hello6():
    print("hello 6th times.")

print_hello5()
print('')
print_hello6()

#80% rot guava before call
#hello 5th times.
#80% rot guava after call
#
#30% rot banana before call
#hello 6th times.
#30% rot banana after call

參考網站:
Python Decorator 四種寫法範例 Code
[python] decorator 之很難理解的快速理解法

留言