Multi-Adorner in Python

Source: Internet
Author: User
Multiple adorners, that is, multiple adorners decorate the same object "It's not exactly the same, and look at the details below."

1. Adorner no parameters:
Copy the Code code as follows:


>>> 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 () is post to first ()
>>> Test ()
Call the function _second () in _first ().
Call the function test () in _second ().
' Hello World '
>>>

In fact it is equivalent to the following code:
Copy the Code code as follows:


>>> def Test ():
Return ' Hello World '

>>> Test=second (Test)
Test () was post to second ()
>>> Test

>>> Test=first (Test)
_second () is post to first ()
>>> Test

>>> Test ()
Call the function _second () in _first ().
Call the function test () in _second ().
' Hello World '
>>>


2. The adorner has parameters:
Copy CodeThe code is as follows:


>>> 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 () is 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 ().
>>>

As above, the 35th line is output after calling __second (), and __second () calls test () and print test (), and then returns to __first () to proceed with print, and the print statement print is __second ( ) returns the None

It is equivalent to:

Copy the Code code as follows:


>>> def Test ():
Return ' Hello World '

>>> Test=second (True) (test)
Test () was post to _second ()
>>>
>>> Test

>>> Test=first (True) (test)
__second () is post to _first ()
>>> Test

>>>


3. Multi-Adorner application:

For example, if you are a project manager, you require that each block of code must have parameter checking Argstype and a responsibility check responsibilityregister, which requires two adorners to supervise this block of code.
Copy the Code code as follows:


#coding =utf-8
Import Os,sys,re
From collections Import Ordereddict

def argstype (*argtypes,**kwtypes):
U ' Argstype (*argtypes,**kwtypes)
options=[(' Opt_usetypeofdefaultvalue ', False)]

The following switches are related to this function, not the keyword parameters associated with type checking, all options:
Opt_usetypeofdefaultvalue=>bool:false, when True, will have a default of the specified type
The value parameter uses the type of its default value
'''
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
#将 all the Options keyword arguments in the parameter type keyword parameter
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 the type of parameter
If options[' Opt_usetypeofdefaultvalue ']:
For k,v in Defaults.items ():
#如果default parameter type is not specified otherwise, use the
The type of the default value of the #default parameter
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 is 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)

There are no documents here, so the caller does not know that using the wrong call causes an error, which is Kate's responsibility.

Like the above, you can use a multi-adorner when you have two unrelated tests of the code.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.