网站首页  汉语字词  英语词汇  考试资料  写作素材  旧版资料

请输入您要查询的考试资料:

 

标题 Python中的多重装饰器
内容
    多重装饰器,即多个装饰器修饰同一个对象【实际上并非完全如此,且看下文详解】
    1.装饰器无参数:
    代码如下:
    >>> 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'
    >>>
    实际上它是相当于下面的代码:
    代码如下:
    >>> 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'
    >>>
    2.装饰器有参数:
    代码如下:
    >>> 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
    它等同于:
    代码如下:
    >>> 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>
    >>>
    3.多重装饰器的应用:
    比如你是项目经理,你要求每一个代码块都必须有参数检查ArgsType和责任检查ResponsibilityRegister,这样就需要两个装饰器对此代码块进行监督。
    代码如下:
    #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的责任。
    像上面这种,对代码有两种互不相干的检验时,就可以使用多重装饰器。
随便看

 

在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。

 

Copyright © 2002-2024 cuapp.net All Rights Reserved
更新时间:2025/5/22 3:27:17