2017年3月13日 星期一

[ Python 常見問題 ] Python object field being passed to decorator as arguments?

Source From Here 
Question 
How do I pass a object field to a decorator on a class method as an argument? What I want to do is something like: 
- test3836.py 
  1. #!/usr/bin/env python  
  2. import functools  
  3.   
  4. def check_authorization(*args, **kw):  
  5.     print "Doing authorization"  
  6.     for a in args:  
  7.         print "\t%s" % (a)  
  8.     def wrapper(f):  
  9.         def dfun(*args, **kw):  
  10.             result = f(*args, **kw)  
  11.             return result  
  12.         return dfun  
  13.     return wrapper  
  14.   
  15. class Client(object):  
  16.     def __init__(self, url):  
  17.         self.url = url  
  18.   
  19.     @check_authorization('some_attr'"self.url")  
  20.     def get(self):  
  21.         print "Get"  
  22.         self.do_work()  
  23.   
  24.     def do_work(self):  
  25.         print "Doing work"  
  26.   
  27.   
  28. client = Client("http://test.org")  
  29. client.get()  
Execution output: 
Doing authorization
some_attr
self.url
Get
Doing work

How-To 
Instead of passing in the instance attribute at class definition time, check it at runtime: 
  1. #!/usr/bin/env python  
  2. import functools  
  3.   
  4. def check_authorization(*args, **kw):  
  5.     for a in args:  
  6.         print "Decorator argu=%s" % (a)  
  7.     def wrapper(f):  
  8.         def dfun(*args, **kw):  
  9.             print "Doing authorization on URL=%s" % (args[0].url)  # args[0] -> self  
  10.             result = f(*args, **kw)  
  11.             return result  
  12.         return dfun  
  13.     return wrapper  
  14.   
  15. class Client(object):  
  16.     def __init__(self, url):  
  17.         self.url = url  
  18.   
  19.     @check_authorization('some_attr')  
  20.     def get(self):  
  21.         print "Get"  
  22.         self.do_work()  
  23.   
  24.     def do_work(self):  
  25.         print "Doing work"  
  26.   
  27.   
  28. client = Client("http://test.org")  
  29. client.get()  
Execution output: 
Decorator argu=some_attr
Doing authorization on URL=http://test.org
Get
Doing work

The decorator intercepts the method arguments; the first argument is the instance, so it reads the attribute off of that. You can pass in the attribute name as a string to the decorator and use getattr if you don't want to hardcode the attribute name: 
  1. #!/usr/bin/env python  
  2. import functools  
  3.   
  4. def check_authorization(*dargs, **dkw):  
  5.     for a in dargs:  
  6.         print "Decorator argu=%s" % (a)  
  7.     def wrapper(f):  
  8.         def dfun(*args, **kw):  
  9.             print "Doing authorization on URL=%s" % (getattr(args[0], dargs[0]))  
  10.             result = f(*args, **kw)  
  11.             return result  
  12.         return dfun  
  13.     return wrapper  
  14.   
  15. class Client(object):  
  16.     def __init__(self, url):  
  17.         self.url = url  
  18.   
  19.     @check_authorization('url')  
  20.     def get(self):  
  21.         print "Get"  
  22.         self.do_work()  
  23.   
  24.     def do_work(self):  
  25.         print "Doing work"  
  26.   
  27.   
  28. client = Client("http://test.org")  
  29. client.get()  
Execution output: 
Decorator argu=url
Doing authorization on URL=http://test.org

Get
Doing work

Supplement 
[Python 學習筆記] 進階議題 : 修飾器 (函式修飾器) 
[ Python 文章收集 ] Decorators I: Introduction to Python Decorators

沒有留言:

張貼留言

[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...