[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 測試

  1. def logged(func):
  2. print('entry init enter')
  3. def with_logging(*args, **kwargs):
  4. print("Entering", func.__name__)
  5. print("arg:",*args)
  6. print("kwarg:",**kwargs)
  7. result = func(*args, **kwargs)
  8. print("Exited", func.__name__)
  9. return result
  10. print('entry init exit')
  11. return with_logging
  12. print('decorator using')
  13. @logged
  14. def f(x):
  15. """does some math"""
  16. return x * x
  17.  
  18. print('test start')
  19. print(f(3))

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

Decorator Class 測試

  1. class entryExit(object):
  2.  
  3. def __init__(self, f):
  4. print('entry init enter')
  5. self.f = f
  6. print('entry init exit')
  7.  
  8. def __call__(self, *args, **kwargs):
  9. print("Entering", self.f.__name__)
  10. r = self.f(*args, **kwargs)
  11. print("Exited", self.f.__name__)
  12. return r
  13.  
  14. print('decorator using')
  15.  
  16. @entryExit
  17. def hello(a):
  18. print('inside hello')
  19. return("hello world " + a)
  20.  
  21. print('test start')
  22. print(hello('friends'))

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

四種寫法

沒有參數的 Decorator Function
  1. def decorateApple(f):
  2. def d_f(*args, **kargs):
  3. print("apple before call")
  4. result = f(*args, **kargs)
  5. print("apple after call")
  6. return result
  7. return d_f
  8.  
  9. @decorateApple
  10. def print_hello():
  11. print("hello first time.")
  12.  
  13. print_hello()
  14.  
  15. #apple before call
  16. #hello first time.
  17. #apple after call

有參數的 Decorator Function
  1. def decorateFruit(fruit, rotLevel):
  2. def outer_d_f(f):
  3. def d_f(*args, **kargs):
  4. print("%s %s before call" % (rotLevel, fruit))
  5. result = f(*args, **kargs)
  6. print("%s %s after call" % (rotLevel, fruit))
  7. return result
  8. return d_f
  9. return outer_d_f
  10.  
  11. @decorateFruit('banana', 'new')
  12. def print_hello2():
  13. print("hello 2nd time.")
  14.  
  15. @decorateFruit('guava', '50% rot')
  16. def print_hello3():
  17. print("hello 3th time.")
  18.  
  19. print_hello2()
  20. print('')
  21. print_hello3()
  22.  
  23. #new banana before call
  24. #hello 2nd time.
  25. #new banana after call
  26. #
  27. #50% rot guava before call
  28. #hello 3th time.
  29. #50% rot guava after call

沒有參數的 Decorator Class
  1. class decorateAppleClass(object):
  2. def __init__(self, f):
  3. self.f = f
  4. def __call__(self, *args, **kargs):
  5. print("apple before call")
  6. result = self.f(*args, **kargs)
  7. print("apple after call")
  8. return result
  9.  
  10.  
  11. @decorateAppleClass
  12. def print_hello4():
  13. print("hello 4th time.")
  14.  
  15. print_hello4()
  16.  
  17. #apple before call
  18. #hello 4th time.
  19. #apple after call

有參數的 Decorator Class
  1. class decorateFruitClass(object):
  2. def __init__(self, fruit, rotLevel):
  3. self.fruit = fruit
  4. self.rotLevel = rotLevel
  5.  
  6. def __call__(self, f):
  7. def d_f(*args, **kargs):
  8. print("%s %s before call" % (self.rotLevel, self.fruit))
  9. result = f(*args, **kargs)
  10. print("%s %s after call" % (self.rotLevel, self.fruit))
  11. return result
  12. return d_f
  13.  
  14. @decorateFruitClass('guava', '80% rot')
  15. def print_hello5():
  16. print("hello 5th times.")
  17.  
  18. @decorateFruitClass('banana', '30% rot')
  19. def print_hello6():
  20. print("hello 6th times.")
  21.  
  22. print_hello5()
  23. print('')
  24. print_hello6()
  25.  
  26. #80% rot guava before call
  27. #hello 5th times.
  28. #80% rot guava after call
  29. #
  30. #30% rot banana before call
  31. #hello 6th times.
  32. #30% rot banana after call

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

留言