2. What is closure

# Define a function
def test(number):
# Define a function inside the function, and the function uses the variables of the outer function. Then call this function and some variables used closure.
def test_in(number_in):
print("in test_in function, number_in is %d" % number_in)
return number+number_in
# In fact, what is returned here is the result of the closure.
return test_in
# To assign a value to the test function, this 20 is to give the number of parameters.
ret = test(20)
# Note that 100 here actually gives the parameter number_in
print(ret(100))
#Note that 200 here actually gives the parameter number_in
print(ret(200))

3. Look at a practical example of closures:

In this example, the function line and variables A and B form closures. When creating closures, we illustrate the values of these two variables through the parameter a and B of line_conf, so that we determine the final form of the function (y = x + 1 and y = 4x + 5). We can obtain different linear expression functions by changing parameters a and B. From this, we can see that closures can also improve code reusability.

If there are no closures, we need to specify a,b,x every time we create a linear function. In this way, we need more parameter passing, which also reduces the portability of the code.

Note:

Because closures refer to local variables of external functions, local variables of external functions are not released in time and memory is consumed.

Decorator

Decorator is a function that is often used in program development. With good use of decorator, development efficiency is like a tiger's wings. So this is also a question that Python interviews must ask. But for many people who have first contacted this knowledge, this function is somewhat circumvented. When they study by themselves, they go around directly, and then they hang up when they come to the interview. Because decorator is the basic knowledge of program development, this will not be. Don't tell people that you know Python, read the following article, to ensure that you learn decorator.

The function name is only a variable, but it points to the defined function, so it can be called through the function name (). If the function name = xxx is modified, then when the function name () is executed, the called function is unknown.

2. Demand is coming

Start-up companies have N business departments, the basic platform department is responsible for providing the underlying functions, such as: database operations, redis calls, monitoring API and other functions. When business departments use basic functions, they only need to call the functions provided by the basic platform. As follows:

At present, the company is in an orderly way, but in the past, the developers of the basic platform did not pay attention to validation when writing code, that is, the functions provided by the basic platform can be used by anyone. Now it is necessary to reconstruct all the functions of the basic platform and add verification mechanism for all the functions provided by the platform, that is, validation before executing the functions.

The boss gave the job to Low B, and he did so:
Negotiate with each business department. Each business department writes its own code and verifies before calling the functions of the underlying platform. In this way, the underlying platform does not need to be modified. That's great. There's plenty of time to pick up girls.

The boss looked at the realization of Low BBB, the corner of his mouth leaked a trace of gratifying laughter, and he talked with Low BBB for a day with a long focus.

The boss said:
Writing code should follow the principle of open and closed. Although this principle is object-oriented development, it is also applicable to functional programming. In short, it stipulates that the implemented functional code is not allowed to be modified, but can be extended, that is:

Closed: Implemented Functional Code Block
Openness: Extension Development
If the principle of open and closed is applied to the above requirements, then it is not allowed to modify the code inside the functions f1, f2, f3 and f4. The boss gives Low BBB an implementation scheme:

For the above code, only modifying the code of the underlying platform can realize the operation of [validation] before other people call the function f1 f2 f3 f4, and other business departments need not do any operation.

Low BBB asked in horror, what is the internal execution principle of this code?

The eldest brother was about to get angry. Suddenly, the mobile phone of Low BBB dropped to the ground. The screen saver happened to be the picture of his girlfriend. As soon as he looked at it, he shook and smiled, and decided to make a good friend with Low BBB.

The python interpreter interprets the code from top to bottom, as follows:

Def w1 (func): ==> load w1 function into memory
@w1
Yes, on the face of it, the interpreter will only interpret these two lines of code, because the function's internal code will not be executed until it is called.

On the face of it, the interpreter will actually execute these two sentences, but there is a big article in the @w1 code. The @function name is a kind of grammatical sugar of python.

The above example @w1 will perform an operation internally:Execute w1 function
Execute the W1 function and take the function under @w1 as a parameter of the W1 function, that is, @w1 is equivalent to w1(f1), so it will be executed internally:

def inner():
#Verification 1
#Verification 2
#Verification 3
f1() # Func is a parameter, where func equals f1
return inner# Inner, inner is a function, not an executable function, which is actually to put the original f1 function into another function.

Return value of w1
The return value of W1 function is assigned to the function name F1 of the function under @w1, that is, the return value of W1 is reassigned to f1.

So, when the business department wants to execute the f1 function, it will execute the new f1 function. First, it will execute the validation inside the new f1 function, then it will execute the original f1 function, and then return the return value of the original f1 function to the business caller.

In this way, the function of validation is executed, the content of the original f1 function is executed, and the return value of the original f1 function is returned to the business call.

Do you understand Low BBB? If you don't understand, I'll go to your house at night and help you solve it!!!

The above code understands the decorator's execution behavior as follows

foo = timefun(foo)
# After foo is assigned to func as a parameter, foo receives wrapped_func pointing to the return of timefun
foo()
# Call foo(), that is, wrapped_func()
# The internal function wrapped_func is referenced, so the func variable (free variable) of the external function is not released.
# The original foo function object is saved in func

Example 6: Class Decorator (Extension, Non-emphasis)
The decorator function is actually an interface constraint that accepts a callable object as a parameter and then returns a callable object. In Python, callable objects are functions, but there are exceptions. As long as an object overrides the call() method, the object is called able.

class Test(object):
def __init__(self, func):
print("---Initialization---")
print("func name is %s"%func.__name__)
self.__func = func
def __call__(self):
print("---Functions in Decorators---")
self.__func()
#Explain:
#1. When using Test as a decorator to decorate the test function, an instance object of Test is created first.
# And pass the function name test as a parameter to the _init_ method
# That is, the attribute _func in the _init_ method points to the function pointed to by the test.
#
#2. test points to instance objects created with Test
#
#3. When invoked using test(), it is equivalent to having the object (), so the _call_ method of the object is invoked.
#
#4. In order to call the function body pointed to by the original test in the _call_ method, an instance attribute is needed in the _init_ method to save the reference of the function body.
# So we have the code self. _func = func, so that we can call the function body before test in the call _call_ method.
@Test
def test():
print("----test---")
test()
showpy()#If you annotate this sentence and re-run the program, you will still see "--initialization--"

The results are as follows:

---Initialization---
func name is test
---Functions in Decorators---
----test---