<> Learning objectives ： Describe the ornament clearly in one breath

There are three things to understand before figuring out the decorator ：
Function object , Function nesting , Function composition closure .

<> Learning content ： Function object , Function nesting , closure , Decorator

Function objects are easy to say ,python Programming languages are dynamic languages ,python Everything is an object , So functions are also objects .
Function objects are represented by function names （ Name only , No parentheses , There are no parameters ）.

for example , A summation function is defined add, So here add It's a function object .
Nested or nested functions , Is when you define a function , There are also operations to define functions in the function body .（def and def Nesting of ）

for example ： Define function check_admin Time , still def Another function . Define another function in the process of defining one function .
def check_admin(): def wrapper(): ... return return
Closures are actually special nested functions .
Nested functions satisfy the following conditions: ： The return value of the outer function is the inner function object （ It is also the function object explained earlier ）. That is, after the closure is defined , It can also be called after creation . for instance

such as ： Closure to realize the operation of univariate quadratic equation
# Define closure ： Define special nested functions def func(a, b, c): def quadratic_equation(x): return a*x**2 + b
Here is ： The outer function is defined func, return return Inner function object quadratic_equation
test + debugging ：
# Call closure , Return new function ,QE Quoted quadratic_equation Function opposite QE = func(5, 5, 5) # Call new function val = QE(2)

One might wonder ： Formal parameter a,b,c Is the value passed to quadratic_equation Equation in function a*x**2 + b*x + c
Yes , They all have different scopes ? yes , Yes , Don't doubt . The inner function will find the function within its scope first , No, I'll look up , An error is reported until it is not found . conversely , The variables of the inner function are only useful within the inner function .

Decorator ： Understand the function object , Function nesting , And after closure , Decorators are a little more special on the basis of closures . Formally , The decorator is the outer layer of the nested two-layer function, and the parameter of the function is the function object . namely
Arguments are closures of function objects , This is the shape structure . After reading this example , Then summarize the concept .

for example ： A decorator for judging users
!= 'admin' and 'admin' not in args: raise Exception("This User do not have
permission") return func(*args, **kwargs) return wrapper
This is a decorator , The decorated object is the parameter to be input –func A function object （ Method or operation ）.

such as ： I'll decorate it before pressing the stack . Just define push Add a headdress when you need it , that push Will be passed as a parameter to func.

You can imagine , If you are operating a database or personal data , The use of each method should judge whether you have permission , Or I won't let you move the data , If , There are more than one operations such as addition, deletion and modification , Do you have to write a lot of duplicate code ? So at this time , Our decorators are very useful , Make the action of judging authority into a headdress , no , Decorator , Send to each method , Go to the front of the action , Save a lot of code . When the method is called again for data operation , The decorated function will automatically help you verify the user permissions . How good !

Complete the example of user permissions ：
# Decorator def check_admin(func): def wrapper(*args, **kwargs): if kwargs.get(
not have permission") return func(*args, **kwargs) return wrapper class Stack:
raise Exception("no element in stack") return self.item.pop()
test + debugging , Look at the results

When username no admin When ,raise abnormal , Data manipulation is not allowed .

The stack operation is also covered with the following permissions of the decorator , Reoperation data . If there are other modifications , update operation , You can also put on the decorator . Very convenient .

Um ...
These are the simple and clear decorations , Poor me N second , I don't understand .n>10
There was a reason .
first , The decorator structure cannot be remembered , Unclear use is the main reason .
then , Function object and closure The two concepts are not well understood ,
last , things seldom seen are strange , read without thorough understanding .
Why don't you understand ?

summary ：

「 Decorator 」 by Python An important part of high-level language features , Is a super convenient way to modify functions , Proper use can effectively improve the readability and maintainability of the code , Very convenient and flexible .
「 Decorator 」 It's essentially a function , The characteristic of this function is that it can accept other functions as its parameters , And transform it into a new function .

<> Advanced learning ： Decorator with parameters

*
Common decorators ：
@classmethod Class method decorator ： Add this decorator to the definition class method , It becomes a class method , Instead of instance methods . in other words , Add a decorator when defining , Its first parameter cls
This class object is referenced , That is, the class itself is passed to this method as a reference object . Not controlled by instance .
@staticmethod
Static method decorator ： Add this decorator to the definition class method , It becomes a static method of the class . in other words , This method was not defined self parameter , When calling this method, you can call it through the class , It can also be called through an instance .

*
Can the decorator transmit reference ?

The answer is ： can . For example, I want to know which method added my decorator . for example ： Add a layer of parameter transfer function to the decorator , Routine level 1 .
# Decorator with parameters def new_tips(argv): def tips(func): def wrapper(*args): print(
" Decorative content ：{}".format(argv)) return func(*args) return wrapper return tips @new_tips(
"add") def add(a, b): print(f"{a}+{b}={a + b}") return a + b @new_tips("sub")
def sub(a, b): print(f"{a}-{b}={a - b}") return a - b
test + debugging