python wraps decorator

来源:互联网 发布:网络的危害 编辑:程序博客网 时间:2024/06/16 16:42
frominspectimportgetmembers, getargspec
fromfunctoolsimportwraps
 
defwraps_decorator(f):
    @wraps(f)
    defwraps_wrapper(*args,**kwargs):
        returnf(*args,**kwargs)
    returnwraps_wrapper
 
classSomeClass(object):
    @wraps_decorator
    defmethod(self, x, y):
        pass
 
obj=SomeClass()
forname, funcingetmembers(obj, predicate=inspect.ismethod):
    print"Member Name: %s"%name
    print"Func Name: %s"%func.func_name
    print"Args: %s"%getargspec(func)[0]
 

classmyDecorator(object):
 
    def__init__(self, fn):
        print"inside myDecorator.__init__()"
        self.fn=fn
 
    def__call__(self):
        self.fn()
        print"inside myDecorator.__call__()"
 
@myDecorator
defaFunction():
    print"inside aFunction()"
 
print"Finished decorating aFunction()"
 
aFunction()


你会发现,即使是你你用了functools的wraps,你在用getargspec时,参数也不见了。

要修正这一问,我们还得用Python的反射来解决,下面是相关的代码:

1
2
3
4
5
6
7
8
9
10
11
12
defget_true_argspec(method):
    argspec=inspect.getargspec(method)
    args=argspec[0]
    ifargsandargs[0]=='self':
        returnargspec
    ifhasattr(method,'__func__'):
        method=method.__func__
    ifnothasattr(method,'func_closure')ormethod.func_closure isNone:
        raiseException("No closure for method.")
 
    method=method.func_closure[0].cell_contents
    returnget_true_argspec(method)

当然,我相信大多数人的程序都不会去getargspec。所以,用functools的wraps应该够用了。

classMyApp():
    def__init__(self):
        self.func_map= {}
 
    defregister(self, name):
        deffunc_wrapper(func):
            self.func_map[name]= func
            returnfunc
        returnfunc_wrapper
 
    defcall_method(self, name=None):
        func= self.func_map.get(name, None)
        iffunc isNone:
            raiseException("No function registered against - "+ str(name))
        returnfunc()
 
app= MyApp()
 
@app.register('/')
defmain_page_func():
    return"This is the main page."
 
@app.register('/next_page')
defnext_page_func():
    return"This is the next page."
 
printapp.call_method('/')
printapp.call_method('/next_page')

 
0 0