Exploration of python decorators and collection of parameters, and decoration of python
First, go to the original article,
Now, let's assume that we want to enhance the functions of the now () function, for example, to automatically print logs before and after the function call, but do not want to modify the definition of the now () function, this way of dynamically adding features during code execution is called the Decorator ).
In essence, decorator is a high-level function that returns a function.
What is the essence of Decorator?
I tried it ..
1 def g (): 2 print ("here is G") 3 return "G" 4 5 @ g 6 def f (): 7 print ("here is F ") 8 return 1 9 ''' 10 ---------------------------------------------- 11 line 5, in <module> 12 @ g13 TypeError: g () takes 0 positional arguments but 1 was given14> 15 '''
Run the result in the comment
Embarrassed... g is forced to insert a parameter, which should be g "modified object"
Modify and continue .....
Def g (f): print ("here is G") return "G" @ gdef f (): print ("here is F ") return 1 ''' ---------------------------------------------- here is G> f () Traceback (most recent call last): File "<pyshell #0>", line 1, in <module> f () TypeError: 'str' object is not callable '''
The str object cannot be called. Here, there is only one str, which is the return value of g.
To verify, I changed "G" to 2
The result is
TypeError: 'int' object is not callable
OK, which means that the decorator is first inserted with a parameter, and then the return value is called again. However, it seems that only the function can be called. Therefore, in order not to report an error, the decorator must return a function. The decorator must be a high-order function ......
I mean I'm not satisfied. Isn't it a function? The g parameter is a function.
Def g (f): print ("here is G") return f @ gdef f (): print ("here is F ") return 1 ''' ------------------------------------------------ here is G >>> f () Here is f'1 ''''
It runs successfully. But... say "log printing", # yes. "Here is G" is the log I want.
Question: printed "here is G" is the first line, which occurs before "f ()" is input ....
# Simply look at the g function, it is not a "high-order function"
As an example of success, it is too failed.
# Well, I surrender, and it's not very interesting to be stubborn .....
The closure tells us the truth. To ensure that the returned value must be a function, the best way is to "Create a function inside the function and then throw it out"
Def g (f): print ("here is G") def h (): print ('here is H') return "H" return H @ gdef f (): print ("here is F") return 1 ''' ------------------------------------------------ here is G >>> f () Here is h'h' >>> f () here is H 'H'> '''
The f function is not executed. Yes, yes. I tried it again.
In addition, the two logs can only be used... (as described below)
After reading the book, if the h function returns f (), the f function will be executed"
Def g (f): print ("here is G") def h (): print ('here is H') return f () return H @ gdef f (): print ("here is F") return 1 ''' ---------------------------------------------- here is G >>> f () Here is H here is f'1' >>> F <function g. <locals>. h at 0x0000020CBDBB6C80> '''
According to the ideas in the book
''' @ Gdef f (): pass >>> f () is equivalent to >>> g (f) () g Function execution, return >>> h () h function execution (log printing) >>> f () f execution, return 1 >>> 1 '''
Add parameters,
Def g (f): print ("here is G") def h (* args, ** kw): print ('here is H') return f (* args, ** kw) return h @ gdef f (* args, ** kw): print ("F") return 1'> f (* args, ** kw) is equivalent to> g (f) (* args, ** kw) g Function execution, return> h (* args, ** kw) h function execution (print logs) >>> f (* args, ** kw) f execution, returns 1 >>> 1 '''
It can be seen that (* args, ** kw) is taken away by the h function. So, observe the h function, and h gives its parameters to f.
I am confused.
Def g (f): print ("here is G") def h (): # The parameter print is not required for h ('here is H ') return f return h @ gdef f (* args, ** kw): print ("F") return 1 ''' >>> f () (* args, ** kw) is equivalent to> g (f) (* args, ** kw) g Function execution, return> h () (* args, ** kw) h function execution, null parameter (print log) in h> f (* args, ** kw) f execution, returns 1> 1 '''
However, a new problem arises. An empty bracket is added when the fbutton is used later. Otherwise
''' >>>> F (* args, ** kw) is equivalent to >>> g (f) (* args, ** kw) g Function execution, return >>> h (* args, ** kw) h function execution (log printing) returns f >>> f is a function object '''
The above tells us a truth."Whether the function is executed or not depends on whether there are any parentheses"
For example
def m(a): print(a) return mprint(m(1)(2)(3)(4)(5)(6)(7)(8)(9)(10))'''-----------------------------12345678910<function m at 0x000002832BDB10D0>
Brain burning time
F = a. B. c () [0] () [d () [e]
The Class B c method of module a is a high-order function, and a list is returned. The list contains a function.
The function returns a dictionary ............
Starting from below, the layer-3 nesting of the decorator
The problem it solves is that the decorator requires additional parameters. How can this problem be solved?
That is, if g (m) is changed to g (canshu) (m) and an extra bracket is added, a function is added. Otherwise, an error occurs.
>>> 1() 1()TypeError: 'int' object is not callable
. Modified
Def I (canshu): def g (f): print ("here is G") def h (* args, ** kw): print ('here is H ') return f (* args, ** kw) return h return g @ I ('canshu') def f (* args, ** kw): print ("here is F ") return 1 ''' ---------------------------------------------- here is G >>>> f () Here is H here is f'1' >>> F <function I. <locals>. g. <locals>. h at 0x00000283A6886D08> '''
Explain
''' >>> F (* args, ** kw) is equivalent to >>> I ('canshu') (f) (* args, ** kw) I function returns g >>> g (f) (* args, ** kw) g Function execution, returns h >>> h (* args, ** kw) h function execution (print logs) returns f (* args, ** kw)> f (* args, ** kw) f execution returns 1 >>> f is equivalent to >>> I ('canshu') (f) I function returns g >>> g (f) g Function execution, return h >>> h. This is a function object '''
So
>>> F. _ name __
'H'
It's a real hijacking, __name _ all changed...
Why is there
It should be understandable
The decorator is executed once when the @ I ('canshu') Statement is executed.
'''> I ('canshu') (f) I function returns g >>> g (f) g Function execution, print a sentence, returns the h> h function object '''
Verify
Def I (canshu): def g (f): print (f. _ name _) print ('here is G') def h (* args, ** kw): print ('here is H') return f (* args, ** kw) return h return g @ I ('canshu') def f (* args, ** kw): print ("F ") return 1 ''' ---------------------------------------------- f here is G >>>> f () Here is H here is f'1 ''''
To sum up, new revelations
In addition, the "hijacking" can also be used for debugging. When two functions do not know which one is better
Def I (f_1): def g (f): def h (* args, ** kw): print ('% s replaced % s' % (f_1. _ name __, f. _ name _) return f_1 (* args, ** kw) return h return gdef f_1 (* args, ** kw): print ("F_1 ") return 2 @ I (f_1) def f (* args, ** kw): print ("F") return 1 ''' ---------------------------------------------------- >>> f () f_1 replaces f with F_12 '''
F = f_1 (> ω <*)
It should be done ,,,
Make up for any omissions
I suddenly felt that this essay was in the embarrassing situation of "I can't understand it, but I can't understand it .....
.