Python multi-decoration, python Decoration

Source: Internet
Author: User

Python multi-decoration, python Decoration

Multiple decorators are used to modify the same object]

1. the decorator has no parameters:

 1 >>> def first(func): 2     print '%s() was post to first()'%func.func_name 3     def _first(*args,**kw): 4         print 'Call the function %s() in _first().'%func.func_name 5         return func(*args,**kw) 6     return _first 7  8  9 >>> def second(func):10     print '%s() was post to second()'%func.func_name11     def _second(*args,**kw):12         print 'Call the function %s() in _second().'%func.func_name13         return func(*args,**kw)14     return _second15 16 17 >>> @first18 @second19 def test():return 'hello world'20 21 test() was post to second()22 _second() was post to first()23 >>> test()24 Call the function _second() in _first().25 Call the function test() in _second().26 'hello world'27 >>> 

 

In fact, it is equivalent to the following code:

 1 >>> def test(): 2     return 'hello world' 3  4 >>> test=second(test) 5 test() was post to second() 6 >>> test 7 <function _second at 0x000000000316D3C8> 8 >>> test=first(test) 9 _second() was post to first()10 >>> test11 <function _first at 0x000000000316D358>12 >>> test()13 Call the function _second() in _first().14 Call the function test() in _second().15 'hello world'16 >>> 

 

2. the decorator has the following parameters:

 1 >>> def first(printResult=False): 2     def _first(func): 3         print '%s() was post to _first()'%func.func_name 4         def __first(*args,**kw): 5             print 'Call the function %s() in __first().'%\ 6                   func.func_name 7             if printResult: 8                 print func(*args,**kw),'#print in __first().' 9             else:10                 return func(*args,**kw)11         return __first12     return _first13 14 >>> def second(printResult=False):15     def _second(func):16         print '%s() was post to _second()'%func.func_name17         def __second(*args,**kw):18             print 'Call the function %s() in __second().'%\19                   func.func_name20             if printResult:21                 print func(*args,**kw),'#print in __second().'22             else:23                 return func(*args,**kw)24         return __second25     return _second26 27 >>> @first(True)28 @second(True)29 def test():30     return 'hello world'31 32 test() was post to _second()33 __second() was post to _first()34 >>> test()35 Call the function __second() in __first().36 Call the function test() in __second().37 hello world #print in __second().38 None #print in __first().39 >>> 

As shown above, after 35th rows are output, _ second () is called, while _ second () calls test () and print test (), and then returns _ first () and the print content of this print statement is None returned by _ second ().

It is equivalent:

>>> 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. Application of Multiple decorations:

For example, if you are a project manager, you require that each code block have a parameter check ArgsType and a responsibility check ResponsibilityRegister. In this way, you need two decorators to supervise the code block.

# Coding = utf-8import OS, sys, refrom collections import OrderedDictdef ArgsType (* argTypes, ** kwTypes): u'''argstype (* argTypes, ** kwTypes) options = [('opt _ usetypeofdefavalue value', False)] the following function-related switches are not key parameters related to the type test. All options: opt_usetypeofdefavalue => bool: False, if this parameter is set to True, ''def _ ArgsType (func) of the default type will be used for parameters without a specified type with a recognized value ): # determine all parameter name argNames = func. func_code.co_varnames [: func. func_code.co_argcount] # determine all default parameter defaults = func. func_defaults if defaults: defaults = dict (zip (argNames [-len (defaults):], defaults) else: defaults = None # Put all "options keyword Parameters" in "parameter type keyword Parameters" into options = dict () for option, default in [('opt _ usetypeofdefavalue value ', False)]: options [option] = kwTypes. pop (option, default) # The total length of argTypes and kwTypes should be consistent with that of argNames if len (argTypes) + len (kwTypes)> len (argNames ): raise Exception ('too much types to check % s (). '% func. func_name) # Keys in all kwTypes cannot overwrite the names that are occupied in argTypes if not set (argNames [len (argTypes):]). issuperset (set (kwTypes. keys (): raise Exception ('there is some key in kwTypes '+ 'which is not in argNames. ') # determine all the parameters that should have 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 # type if options for default parameter ['opt _ usetypeofdefavalue value']: for k, v in ults. items (): # if the type of the default parameter is not specified separately, use the type of the default value of # 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 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 _ ArgsTypedef ResponsibilityRegister (author ): def _ ResponsibilityRegister (func): def _ ResponsibilityRegister (* args, ** kw): try: return func (* args, ** kw) limit t Exception as e: print ("Something is wrong, It's % s responsibility. "% \ author ). center (80, '*') raise e 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 is no document here, so the caller does not know that it is Kate's responsibility to use an incorrect call, resulting in an error.

As in the above case, when there are two mutually unrelated checks on the code, you can use multiple decorators.

 

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.