<> 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 .
def add(username, a, b): print(f"{a}+{b}={a + b}") return a + b
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
*x + c return quadratic_equation
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
def check_admin(func): def wrapper(*args, **kwargs): if kwargs.get('username')
!= '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 ).
Decorate anyone's head with decoration ( Wear a headdress @check_admin).

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.
@check_admin def push(username, item): items = [] items.append(item)

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(
'username') != 'admin' and 'admin' not in args: raise Exception("This User do
not have permission") return func(*args, **kwargs) return wrapper class Stack:
def __init__(self): self.item = [] @check_admin def push(self, username, item):
self.item.append(item) @check_admin def pop(self, username): if not self.item:
raise Exception("no element in stack") return self.item.pop()
test + debugging , Look at the results
When user username='admin’ When , Stack pressing succeeded .

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 .
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
add1 = add(3, 5) sub1 = sub(8, 2)
actually :@new_tips("add") Medium new_tips("add") amount to tips, Because once executed new_tips("add") Just return tips.
@new_tips("add") Equivalent to @tips, It has become a familiar ornament .

<> Learning output : Learned so much , So can you answer the questions in the written interview ?

for example :
1, What is a closure ?
2, What is the decorator ? What is the function of the decorator ?
3, Have you ever used a decorator ? Please write an example of a decorator ?

Reference book recommendation :《python The way of cultivation 》by Rocky0429