First, the decoration device
An adorner is essentially a function, and its function is to add additional functionality to the decorated function. The use principle of the adorner: (1) cannot modify the source code of the decorated function, (2) cannot modify the calling method of the decorated function, in short, the adorner is transparent to the adornment function. It is often used in scenarios where there is a need for facets, such as inserting logs, performance testing, transaction processing, caching, permission checking, and so on.
1. Preliminary knowledge:
(1) Higher order function: pass a function name as an argument to another function, the return value contains the function name
(2) Nested functions: Declaring a function in a function body, not just calling a function
(3) Adorner = higher order function + nested function
2. Simple Decorator
If we want to count the execution time of a function, we can write a function of the statistic time, and then pass the statistic function as a parameter.
1 Import Time2 defBar ():3Time.sleep (3)4 Print('In the bar')5 defTest1 (func):6Start_time=time.time ()7 func ()8Stop_time =time.time ()9 Print('The func run time is%s'% (Stop_time-start_time))TenTest1 (BAR)View Code
Operation Result:
in is 3.000171661376953
But in that case, we're going to pass a function as an argument to the Test1 function every time. Changed the way the function was called before executing the business logic, running Bar (), but now has to change to Test1 (bar). The decorator is used at this point. We're going to figure out a way to do this. Do not modify the calling code, and if you do not modify the calling code, it means that calling bar () requires the effect of calling Test1 (bar). We can think of assigning test1 to bar, but Test1 seems to have a parameter ... Think of ways to unify the parameters! If Test1 (bar) does not directly produce a call effect, but instead returns a function that is consistent with the Foo argument list ... It's good to have the return value of Test1 (bar) assigned to bar, and then the Code calling bar () does not have to be modified at all!
1 Import Time2 defTimmer (func):3 defdeco ():4Start_time=time.time ()5 func ()6Stop_time=time.time ()7 Print('The func run time is%s'% (stop_time-start_time))8 returndeco9 Ten defBar (): OneTime.sleep (3) A Print('In the bar') -Bar=Timmer (BAR) -Bar ()View Code
Operation Result:
in is 3.000171661376953
The function Timmer is the adorner, which wraps the func that executes the real business method inside the function, and looks like the bar is Timmer decorated. If we want to define a function using adorners, avoid using an assignment statement Bar=timmer (bar), to use the adorner's syntax sugar @
1 Import Time2 defTimmer (func):3 defdeco ():4Start_time=time.time ()5 func ()6Stop_time=time.time ()7 Print('The func run time is%s'% (stop_time-start_time))8 returndeco9 @timmerTen defBar (): OneTime.sleep (3) A Print('In the bar') -Bar ()View Code
Operation Result:
in is 3.000171661376953
In this way, we increase the reusable nature of the program, which can be called directly when other functions need to invoke the adorner. The adorner is so handy in Python that the functions that are attributed to Python can be passed as arguments to other functions as normal objects, and can be assigned to other variables, which can be used as return values and can be defined within another function.
3. Adorner with parameters
If the function to decorate is with parameters
1 Import Time2 defTimmer (func):3 defDeco (*arg,**kwarg):4Start_time=time.time ()5Func (*arg,**Kwarg)6Stop_time=time.time ()7 Print('The func run time is%s'% (stop_time-start_time))8 returndeco9 @timmerTen deftest1 (): OneTime.sleep (1) A Print('In the test1') - @timmer - deftest2 (name,age): theTime.sleep (2) - Print('In the test2:', Name,age) - test1 () -Test2 ('Alex', 18)View Code
Operation Result:
In are1.0000572204589844 in the Test2:alex are 2.0001144409179688
Second, generator
The data is generated before the list is used, but we tend to use only a subset of the data, and most of the data doesn't waste space. The generator generator generates the corresponding data only when it is called.
1. List generation: What to do if you want to generate a list [1x1, 2x2, 3x3, ..., 10x10]? In addition to loops, you can use a single line of statements instead of loop generation
1 for in range (1,11)]2print(list)
View Code
Operation Result:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
This is the Python list generation, when writing the list generation, the elements to be generated X * x to the front, followed by A for loop, you can create a list.
2. Generator: There are a number of ways to create a generator. The first approach is simple, as long as you change a list-generated formula [] () to create a generator
1 for in range (1,11))2print(g)
Operation Result:
<generator Object <genexpr> at 0x005b37e0>
The list difference between creating and making generator is only the outermost [] and()。list的元素我们可以一个个打印出,如果要打印generator中的元素需要借助next方法
1 for in range (1,11))2print(Next (g))3print(Next (g) )4print(Next (g))
View Code
Operation Result:
149
But generator saves the algorithm, each time it is called next(g) , computes g the value of the next element until it is calculated to the last element, no more elements are thrown when the StopIteration error occurs. You can iterate over for it by looping, and you don't need to be concerned about StopIteration the error.
1 for in range (1,11))2 for in G:3 print(i)
View Code
Operation Result:
1 1 2 4 3 9 4 + 5 6 7 8 9 Bayi 100
View Code
3. Generate generator with functions:generator is very powerful. If the calculated algorithm is more complex, and the loop with similar list generation for cannot be implemented, it can also be implemented with functions. For example, the Fibonacci sequence cannot be written with a list generation, but it is easy to print it out with a function:
1 def fib (max): 2 n,a,b=0,0,13while n<Max:4 print(b)5 a,b=b,a+b6 n=n+17 return ' done'8 f=fib (6)
View Code
Operation Result:
1 12 13 24 35 56 8
View Code
The above functions and generator are only a step away. To turn fib a function into a generator, just print(b) change yield b it to:
Python Learning--day4