2017年3月13日 星期一

[Python 文章收集] Python Decorator 四種寫法範例 Code

Source From Here
Preface
Python Decorator 可以以 function 與 class 實作出來,且有無參數的寫法也會因此不一樣,以下記錄了從 Stack Overflow 學習來的 decorator 寫法 {function, class} X {with, without} arguments = 4 種.

Decorator Function

沒有參數的 Function 版本
使用 closure 去處理 function:
  1. def decorateApple(f):  
  2.     print "=== Enter decorator with %s" % (f)  
  3.     def d_f(*args, **kargs):  
  4.         print("=== apple before call")  
  5.         result = f(*args, **kargs)  
  6.         print("=== apple after call")  
  7.         return result  
  8.     print "=== Exit decorator"  
  9.     return d_f  
  10.   
  11. @decorateApple  
  12. def print_hello(name):  
  13.     print("Hello %s." % (name))  
  14.   
  15. print_hello('John')  
Execution output:
=== Enter decorator with
=== Exit decorator
=== apple before call
Hello John.
=== apple after call

有參數的 Decorator Function
需要多一層的 outter function 來傳入參數:
  1. def decorateApple(*dargs, **dkargs):  
  2.     print "=== Enter decorator"  
  3.     for a in dargs:  
  4.         print "==== Arg=%s" % a  
  5.     def outer_d_f(f):  
  6.         print "===== Enter outer_d_f"  
  7.         def d_f(*args, **kargs):  
  8.             print("======= apple before call")  
  9.             result = f(*args, **kargs)  
  10.             print("======= apple after call")  
  11.             return result  
  12.         print "===== Exit outer_d_f"  
  13.         return d_f  
  14.     print "=== Exit decorator"  
  15.     return outer_d_f  
  16.   
  17. @decorateApple('banana')  
  18. def print_hello(name):  
  19.     print("Hello %s." % (name))  
  20.   
  21. print_hello('John')  
Execution output:
=== Enter decorator
==== Arg=banana
=== Exit decorator
===== Enter outer_d_f
===== Exit outer_d_f
======= apple before call
Hello John.
======= apple after call

Decorator Class

沒有參數版本的 Decorator Class
Python 會將被修飾的 function 傳入 __init__,這時就將它存入到 decorator 的 data member self.f 。另外再直接覆寫 __call__ ,然後在呼叫 self.f 的前後作額外的修飾動作。這裡的 __call__ 的 signature ,就是跟 被修飾的 function 一樣,所以就加上動態的 *args, 跟 **kargs 就可以完整 delegate了。
  1. #!/usr/bin/env python  
  2. class decorateAppleClass(object):  
  3.     def __init__(self, f):  
  4.         self.f = f  
  5.   
  6.     def __call__(self, *args, **kargs):  
  7.         print("===== apple before call")  
  8.         result = self.f(*args, **kargs)  
  9.         print("===== apple after call")  
  10.         return result  
  11.   
  12.   
  13. @decorateAppleClass  
  14. def print_hello4(name):  
  15.     print("Hello %s." % (name))  
  16.   
  17. print_hello4('John')  
Execution output:
===== apple before call
Hello John.
===== apple after call

帶有參數版本的 Decorator Class
當有參數版本的 decorator class 在修飾 function 時,function 就不會像沒有參數版本的 decorator class 一樣,會將 function 傳入 __init__,而是會傳入 decorator 的參數。function 本體則是會在 __call__ 中被傳入,這是一個比較不一樣的地方。
  1. #!/usr/bin/env python  
  2. class decorateAppleClass(object):  
  3.     def __init__(self, *dargs, **dkw):  
  4.         print("===== Enter decorator __init__")  
  5.         for a in dargs:  
  6.             print("-----> Arg=%s" % (a))  
  7.   
  8.     def __call__(self, f):  
  9.         def d_f(*args, **kargs):  
  10.             print("===== apple before call")  
  11.             result = f(*args, **kargs)  
  12.             print("===== apple after call")  
  13.             return result  
  14.         return d_f  
  15.   
  16.   
  17. @decorateAppleClass('banana')  
  18. def print_hello4(name):  
  19.     print("Hello %s." % (name))  
  20.   
  21. print_hello4('John')  
Execution output:
===== Enter decorator __init__
-----> Arg=banana
===== apple before call
Hello John.
===== apple after call


沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...