[2020Python cultivation 19] Python syntax introduction function decorator

[directory]

1, Introduction to decorators

1. What is a decorator

2. Why use ornaments

2, The realization of decorator

1. Realization of parameterless decorator

2. Realization of parametric decorator

*Reserve knowledge: (please click the title below to read ~)

1,Namespace and scope

2,Function object + function nesting + closure function 

 

1, Introduction to decorators

1. Why use ornaments

Open and closed principle——

The design of software should follow the principle of open and closed, that is to say, it is open to extension and closed to modification.

Opening to extensions means that when there are new requirements or changes, existing code can be extended to adapt to the new situation.

Closing the modification means that once the object is designed, it can complete its work independently without modification.

 

The source code and calling mode of all functions contained in the software should be avoided to be modified, otherwise, once the error is corrected, it is likely to have a chain reaction and eventually cause the program to crash,

As for the online software, new requirements or changes emerge in endlessly, we must provide the possibility of expansion for the program, which uses the decorator.

 

2. What is a decorator

’Decoration refers to adding new functions to the decorated objects,

’"Decorator" refers to the appliance / tool. Both the decorator and the decorated object can be any callable object.

That is, the function of decorator is to add additional functions to the decorated object without modifying the source code and call mode of the decorated object.

 

Decorators are often used in scenarios with cutting-edge requirements, such as: insert log, performance test, transaction processing, cache, permission verification and other application scenarios. Decorators are an excellent design to solve such problems,

With the decorator, we can extract a lot of identical code which has nothing to do with the function itself and continue to reuse it.  

Tip: callable objects include functions, methods or classes. Here we take the theme functions in this chapter as an example to introduce function decorators, and the decorated objects are also functions.

 

A function decorator is a function defined to add additional functions to other functions.

 

2, The realization of function decorator

Function decorator can be divided into two types: parameterless decorator and parameterless decorator. Both of them are the product of the combination of function nesting + closure + function object.

Follow the principle: do not modify the source code of the decorated object & call method

1. Realization of parameterless decorator

(please keep up with the pace)

(0) requirements - add the function of running time statistics to the index function without modifying its source code and calling method

def index(x,y):
    time.sleep(3)
    print('index %s %s' %(x,y))

index(111,222)
# index(y=111,x=222) #Parameter form of other calls
# index(111,y=222)

(1) Solution 1: failure
Problem: the calling method of the decorated object is not modified, but its source code is modified

import time

def index(x,y):
    start=time.time()
    time.sleep(3)
    print('index %s %s' %(x,y))
    stop = time.time()
    print(stop - start)

index(111,222)

(2) Solution 2: failure
Problem: the calling method of the decorated object is not modified, the source code is not modified, and new functions are added, but the code is redundant

import time

def index(x,y):
    time.sleep(3)
    print('index %s %s' %(x,y))

start=time.time()
index(111,222)
stop=time.time()
print(stop - start)



start=time.time()
index(111,222)
stop=time.time()
print(stop - start)


start=time.time()
index(111,222)
stop=time.time()
print(stop - start)

(3) Solution 3: failure
Problem: it solves the problem of code redundancy in scheme 2, but brings a new problem, that is, the call mode of the function has changed

import time

def index(x,y):
    time.sleep(3)
    print('index %s %s' %(x,y))

def wrapper():
    start=time.time()
    index(111,222)
    stop=time.time()
    print(stop - start)

wrapper()

(4) The main direction of optimization scheme 3: how to keep the function calling mode unchanged on the basis of scheme 3

Optimization 1 of scheme 3: the parameters of index are written

import time

def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

def wrapper(*args,**kwargs):
    start=time.time()
    index(*args,**kwargs) # index(3333,z=5555,y=44444)
    stop=time.time()
    print(stop - start)

# wrapper(3333,4444,5555)
# wrapper(3333,z=5555,y=44444)

Optimization 2 of scheme 3: on the basis of optimization 1, the object to be decorated is written alive, so only index can be decorated

import time

def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)


def outter(func):
    # func = index Memory address of
    def wrapper(*args,**kwargs):
        start=time.time()
        func(*args,**kwargs) # index Memory address of()
        stop=time.time()
        print(stop - start)
    return wrapper

index=outter(index) # index=wrapper Memory address of
home=outter(home) # home=wrapper Memory address of


home('egon')
# home(name='egon')

Optimization of scheme three as like as two peas: three, wrapper is exactly the same as the decorated object.

import time

def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)

def outter(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        stop=time.time()
        print(stop - start)
        return res


    return wrapper
# steal the beams and pillars and replace them with rotten timbers: home The name points to wrapper Memory address of the function
home=outter(home)


res=home('egon') # res=wrapper('egon')
print('Return value-->',res)


(5) Grammar sugar - a kind of grammar sugar that makes you happy. It can be held in your mouth for a long time

How to define and use decorators——

==Define decorators

==Use decorator: write @ decorator name on a separate line directly above the decorated object

import time

#Define decorators

def timmer(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        stop=time.time()
        print(stop - start)
        return res

    return wrapper

# Use decorator: write on a separate line directly above the decorated object@Name of decorator

@timmer # index=timmer(index)
def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

@timmer # home=timmer(ome)
def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)


index(x=1,y=2,z=3)
home('egon')

(6) Summarize the parameterless decorator template

Template:

def outter(func):
    def wrapper(*args,**kwargs):
        # 1,Call the original function
        # 2,Add new features to it
        res=func(*args,**kwargs)
        return res
    return wrapper

Guri Ko:

def auth(func):
    def wrapper(*args, **kwargs):
        # 1,Call the original function
        # 2,Add new features to it
        name = input('your name>>: ').strip()
        pwd = input('your password>>: ').strip()
        if name == 'egon' and pwd == '123':
            res = func(*args, **kwargs)
            return res
        else:
            print('Account password error')

    return wrapper


@auth
def index():
    print('from index')

index()

(7) After eating the sugar, think about what is the loading order and running order when you stack multiple decorators?

@deco1 # index=deco1(deco2.wrapper Memory address of)
@deco2 # deco2.wrapper Memory address of=deco2(deco3.wrapper Memory address of)
@deco3 # deco3.wrapper Memory address of=deco3(index)
def index():
    pass

 

 

2. Realization of parametric decorator

 

 

 

reference material:

https://zhuanlan.zhihu.com/p/109078881

Tags: Python

Posted on Mon, 23 Mar 2020 02:51:31 -0700 by serious1234