源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Python中的多重装饰器

  • 时间:2022-04-08 14:43 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Python中的多重装饰器
多重装饰器,即多个装饰器修饰同一个对象【实际上并非完全如此,且看下文详解】 [b]1.装饰器无参数: [/b]
[u]复制代码[/u] 代码如下:
>>> def first(func):     print '%s() was post to first()'%func.func_name     def _first(*args,**kw):         print 'Call the function %s() in _first().'%func.func_name         return func(*args,**kw)     return _first >>> def second(func):     print '%s() was post to second()'%func.func_name     def _second(*args,**kw):         print 'Call the function %s() in _second().'%func.func_name         return func(*args,**kw)     return _second >>> @first @second def test():return 'hello world' test() was post to second() _second() was post to first() >>> test() Call the function _second() in _first(). Call the function test() in _second(). 'hello world' >>>
实际上它是相当于下面的代码:
[u]复制代码[/u] 代码如下:
>>> def test():     return 'hello world' >>> test=second(test) test() was post to second() >>> test <function _second at 0x000000000316D3C8> >>> test=first(test) _second() was post to first() >>> test <function _first at 0x000000000316D358> >>> test() Call the function _second() in _first(). Call the function test() in _second(). 'hello world' >>>
[b]2.装饰器有参数: [/b]
[u]复制代码[/u] 代码如下:
>>> def first(printResult=False):     def _first(func):         print '%s() was post to _first()'%func.func_name         def __first(*args,**kw):             print 'Call the function %s() in __first().'%\                   func.func_name             if printResult:                 print func(*args,**kw),'#print in __first().'             else:                 return func(*args,**kw)         return __first     return _first >>> def second(printResult=False):     def _second(func):         print '%s() was post to _second()'%func.func_name         def __second(*args,**kw):             print 'Call the function %s() in __second().'%\                   func.func_name             if printResult:                 print func(*args,**kw),'#print in __second().'             else:                 return func(*args,**kw)         return __second     return _second >>> @first(True) @second(True) def test():     return 'hello world' test() was post to _second() __second() was post to _first() >>> test() Call the function __second() in __first(). Call the function test() in __second(). hello world #print in __second(). None #print in __first(). >>>
如上,第35行输出后调用__second(),而__second()中又调用了test()并print test(),而后返回__first()中继续执行print,而这个print语句print的内容是__second()返回的None 它等同于:
[u]复制代码[/u] 代码如下:
>>> def test():     return 'hello world' >>> test=second(True)(test) test() was post to _second() >>> >>> test <function __second at 0x000000000316D2E8> >>> test=first(True)(test) __second() was post to _first() >>> test <function __first at 0x0000000003344C18> >>>
[b]3.多重装饰器的应用:[/b] 比如你是项目经理,你要求每一个代码块都必须有参数检查ArgsType和责任检查ResponsibilityRegister,这样就需要两个装饰器对此代码块进行监督。
[u]复制代码[/u] 代码如下:
#coding=utf-8 import os,sys,re from collections import OrderedDict def ArgsType(*argTypes,**kwTypes):     u'''ArgsType(*argTypes,**kwTypes)     options=[('opt_UseTypeOfDefaultValue',False)]     以下为本函数相关的开关,并非类型检验相关的关键字参数,所有options:     opt_UseTypeOfDefaultValue=>bool:False,为True时,将对没有指定类型的带默                                认值的参数使用其默认值的类型     '''     def _ArgsType(func):         #确定所有的parameter name         argNames=func.func_code.co_varnames[:func.func_code.co_argcount]         #确定所有的default parameter         defaults=func.func_defaults         if defaults:             defaults=dict(zip(argNames[-len(defaults):],defaults))         else:defaults=None         #将“参数类型关键字参数”中的所有“options关键字参数”提出         options=dict()         for option,default in [('opt_UseTypeOfDefaultValue',False)]:             options[option]=kwTypes.pop(option,default)         #argTypes和kwTypes的总长度应该与argNames一致         if len(argTypes)+len(kwTypes)>len(argNames):             raise Exception('Too much types to check %s().'%func.func_name)         #所有kwTypes中的键不能覆盖在argTypes中已经占用的names         if not set(argNames[len(argTypes):]).issuperset(             set(kwTypes.keys())):             raise Exception('There is some key in kwTypes '+                 'which is not in argNames.')         #确定所有的参数应该有的types         types=OrderedDict()         for name in argNames:types[name]=None         if len(argTypes):             for i in range(len(argTypes)):                 name=argNames[i]                 types[name]=argTypes[i]         else:             for name,t in kwTypes.items():                 types[name]=t         if len(kwTypes):             for name,t in kwTypes.items():                 types[name]=t         #关于default parameter的type         if options['opt_UseTypeOfDefaultValue']:             for k,v in defaults.items():                 #如果default parameter的type没有另外指定,那么就使用                 #default parameter的default value的type                 if types[k]==None:                     types[k]=type(v)         def __ArgsType(*args,**kw):             #order the args             Args=OrderedDict()             #init keys             for name in argNames:Args[name]=None             #init default values             if defaults is not None:                 for k,v in defaults.items():                     Args[k]=v             #fill in all args             for i in range(len(args)):                 Args[argNames[i]]=args[i]             #fill in all keyword args             for k,v in kw.items():                 Args[k]=v             #check if there is some None in the values             if defaults==None:                 for k in Args:                     if Args[k]==None:                         if defaults==None:                             raise Exception(('%s() needs %r parameter, '+                                 'which was not given')%(func.func_name,k))                         else:                            if not defaults.has_key(k):                                 raise Exception(('Parameter %r of %s() is'+                                     ' not a default parameter')%\                                     (k,func.func_name))             #check all types             for k in Args:                 if not isinstance(Args[k],types[k]):                     raise TypeError(('Parameter %r of %s() must be '+                         'a %r object, but you post: %r')%\                         (k,func.func_name,types[k],Args[k]))             return func(*args,**kw)         return __ArgsType     return _ArgsType def ResponsibilityRegister(author):     def _ResponsibilityRegister(func):         def __ResponsibilityRegister(*args,**kw):             try:                 return func(*args,**kw)             except Exception as e:                 print ("Something is wrong, It's %s's responsibility."%\                        author).center(80,'*')                 raise e         return __ResponsibilityRegister     return _ResponsibilityRegister @ResponsibilityRegister('Kate') @ArgsType(str,int) def left(Str,Len=1):     return Str[:Len] print 'Good calling:' print left('hello world',8) print 'Bad calling:' print left(3,7)
这里没有文档,所以调用者不知道,使用了错误的调用,导致出错,这是Kate的责任。 像上面这种,对代码有两种互不相干的检验时,就可以使用多重装饰器。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部