The adorner in Python is a very useful thing, and we can write some specific methods and common methods into a decorator, which provides a great convenience for invoking these methods, thus improving the readability and simplicity of our code, as well as extensibility.
Before learning the Python decorator, let's take a look at one of these examples:
First, scope
# coding:utf-8msg = ' Hello test1 ' def add (): msg = ' This is add ' Print msg #当执行add () will print ' This is add '
Def add2 ():
Print msg #当执行add2 () when ' Hello Test1 ' will be printed
The above example simply explains the scope of Python, which states that the global variable Msg,add function also declares a local variable msg, which, when executing the "Print msg" of Add (), will first find if there is a local variable msg in the Add. If you don't find it, go to the top-level scope to find out if the variable exists, local variables are generated when the function is run, and local variables are destroyed when the function ends, and then we deepen the example above:
Second, closed package
# coding:utf-8def Add (): msg = ' Hello add ' def inner (): Print msg #运行add () here will be printed ' Hello Add ' return Inner
>>> obj = Add () >>> obj #可见obj是一个指向inner函数的对象 <function inner at 0x0000000002855438>...> >> obj () hello add #运行obj () print msg
See the above example is not a little puzzled, obj is the object that points to the inner function, when running obj is equivalent to running inner, but the add function is not running, that is, MSG is not declared at the same time inner also does not declare the variable MSG, How does it find the value of the MSG variable?
This is the "closure" in Python, which Python supports a feature called, which, by 函数闭包 employing words, is a nested definition of a 非全局作用域 function that remembers the enclosing namespace it was in when it was defined. This can be done by looking at the function of obj. func_closure The attribute concludes that the attribute contains the value within the enclosing scope (only the value that is captured, and if there are add other values defined in it, the enclosing scope is not)
Closures are the core principle of Python adorners, and we'll write a simple example of adorners:
Three, simple decorative device
# Coding:utf-8def Check_args_num (func): # The adorner is used to check the number of parameters passed in, check if it is two parameters def inner (*args, **kwargs): args_ List = list (args) if Len (args_list) < 2: for I in range (2-len (args)): # Fill in 0 if the number of parameters is less than 2 Args_list.app End (0) if Len (args_list) > 2: # Prints error if number of arguments is greater than 2 print ' The args number is too many! ' Func (*args_list, **kwargs) return inner@check_args_numdef Add (x, y): return x + y
Execution Result:
>>>print Add (3...>>>print) 100...>>>print Add (+) Traceback (most recent Call last): File "D:\PyCharm 5.0.4\helpers\pydev\pydevd_exec.py", line 3, exec exec exp in global_vars, Local_ VARs file ' <input> ', line 1, in <module> file ' e:/code/my_project/decorator/test1.py ', line +, in Inner Raise Exception (' The args number is too many! ') Exception:the args number is too many!... >>>add<function inner at 0x0000000002a6c3c8># You can see that the Add function now points to inner
Four or more adorners
# Coding:utf-8def Check_args_int (func): # This adorner is used to check if an incoming parameter is an int type def ensure_int (*args, **kwargs): from Array Import Array try: Array (' H ', args) except Exception, E: raise Exception (E) return func (* args, **kwargs) return ensure_intdef Check_args_num (func): # The adorner is used to check the number of parameters passed in, to check if it is a two-parameter def inner (*args , **kwargs): args_list = list (args) if Len (args_list) < 2: for I in range (2-len (args)): # If the number of parameters is small 2 in 0 to fill args_list.append (0) if Len (args_list) > 2: # Print error if number of arguments is greater than 2 raise Exception (' the args Number is too many! ') return func (*args_list, **kwargs) return inner@check_args_num@check_args_intdef Add (x, y): return x + y
This adds a parameter content check adorner, when more than one adorner, will be executed from top to bottom, first execute check_args_num and then execute Check_args_int, execute the result:
>>> Print Add (1, ' Fsaf ') Traceback (most recent call last): File "D:\PyCharm 5.0.4\helpers\pydev\pydevd_ exec.py ", line 3, exec exec exp in global_vars, Local_vars File" <input> ", line 1, in <module> File "e:/code/my_project/decorator/test1.py", line inner return func (*args_list, **kwargs) file "e:/ code/my_project/decorator/test1.py ", line ten, in Ensure_int raise Exception (e) exception:an integers is required...& Gt;>> add<function inner at 0x0000000002b1c4a8> #这里可以看到add还是指向inner, we can understand that when multiple adorners are present, when add is called, Its invocation entry is always the first adorner, the first adorner executes, then the next one, and the parameters are passed down sequentially.
Five, with parameters of the adorner
We know that when we define the adorner, the first parameter to the adorner is the decorated function (eg. add in the example), and sometimes we need to pass additional parameters to the adorner, the following example will pass additional parameters to the adorner, as follows:
# Coding:utf-8def Check_args_int (func): # This adorner is used to check if an incoming parameter is an int type def ensure_int (*args, **kwargs): from array im Port array try:array (' H ', args) except Exception, E:raise Exception (e) return Func (*args, **kwargs) return ensure_intdef check_args_num (flag): "':p aram Func: Decorated function:p Aram flag: Determines whether parameters are checked Quantity "# This adorner is used to check the number of parameters passed in, check if it is two parameters Def get_func (func): Def inner (*args, **kwargs): if flag = = ' False ': print ' Skip check! ' return func (*args, **kwargs) args_list = List (args) If Len (args_list) < 2:for i I N Range (2-len (args)): # 0 to fill args_list.append (0) If Len (args_) If the number of parameters is less than 2 List) > 2: # Print error if the number of arguments is greater than 2 raise Exception (' The args ' is too many! ') return func (*args_list, **kwargs) return inner return Get_func@check_args_num ('False ') @check_args_intdef Add (x, y): return x + y
This example only check_args_num and before the difference is that the adorner check_args_num more than one parameter flag, when the flag== ' false ', skip the parameter number check, the following is the output
>>>print Add (1, 2) Skip check!3
Python decorator detailed