程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

How to use Python decorator functions

編輯:Python

Python How to use decorator functions

This article mainly introduces Python Knowledge about how decorator functions are used , The content is detailed and easy to understand , The operation is simple and fast , It has certain reference value , I believe that after reading this article Python How to use decorator functions in the article will be fruitful , Let's have a look .

Suppose I write a function f

def f():    print('hello')

Then I want to know how long this function will take to execute , It's easy to do , I just need to change the code to the following

import timedef f():    start = time.time()   # Get the start time of program execution     print('hello')    end = time.time()     # Get the end time of program execution     print(end - start)    # Get the function f Execution time f()

But then I wrote countless functions f2,f3……fn, I want to know how long each function takes to execute , So if you change everything like the above , Isn't it annoying ? Not yet. , Because it's too much trouble . Then what shall I do? ? So I had an idea , Wrote a timer function ...

import timedef timer(func):    start = time.time()    func()    print(time.time() - start)def f():    print('hello')def f2():    print('xorld')timer(f)timer(f2)

Isn't it a lot easier ? No matter how many functions we write, we can call this timing function to calculate the execution time of the function

But if I just want to do it the same way f1(),f2(),fn() Called this function , The function can also increase the function of calculation time on the premise that the original execution output result remains unchanged , Instead of calling timer(f),timer(f2) To calculate time , What should I do ?

After looking at the decorator function below, you will know how to solve this problem



One 、 Decorator —— Formation process

Here is a simple version of the code that solves the above problem :

import timedef f():    print('hello')def timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return innerf = timer(f)f()

I just want to use the original way f1(),f2(),fn() Called this function , The function can also increase the function of calculation time on the premise that the original execution output result remains unchanged , But I'm still going to be in the function f Write before execution f = timer(f) In this string of code , Do you think it's an eyesore ?python The developers of the company also feel it's an eyesore , therefore python The developers of the java.com provide us with a syntax sugar to solve this problem !



Two 、 Decorator —— First knowledge of grammar sugar

use @timmer Instead of f = timer(f), This is a grammatical sugar .

import timedef timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return [email protected]   #==>  Writing this sentence is equivalent to executing f = timer(f)def f():    print('hello')f()


3、 ... and 、 Decorator —— Essence and function

1、 The essence

  The essence of decorator is a closure function

2、 function

Extend the function of the original function without modifying the original function and its calling method

Four 、 Decorator —— Decorative belt parameters , Decorators that return values

  • 1、 Decorate a function with one argument

The decorators we just wrote are decorating functions without parameters , Now how to decorate a function with parameters ?

import timedef timer(func):    def inner(a):        start = time.time()        func(a)        print(time.time() - start)    return [email protected] f(a):    print(a)f('hello')
  • 2、 Decorate multiple functions with different parameters but no return value

In fact, decorating functions with parameters is not difficult , But if you have two functions , The parameters to be passed are different , such as   function func1 There are two parameters func1(a ,b), function func 2 There is only one parameter func2(a), And they all want to decorate with this decorator , Calculate the function execution time ? So what do we do ? Then use the following code .

import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        print(time.time() - start)        return re    return [email protected]   #==> func1 = timer(func1)def func1(a,b):    print('in func1')@timer   #==> func2 = timer(func2)def func2(a):    print('in func2 and get a:%s'%(a))    return 'fun2 over'func1('aaaaaa','bbbbbb')print(func2('aaaaaa')) Output results :in func10.0in func2 and get a:aaaaaa0.0fun2 over
  • 3、 Decorate multiple functions with different parameters and return values

Now the parameter problem has been solved perfectly , But what if your function has a return value ? With the above code, you can't get the return value. How do you solve this problem ? Let's look at the following code !

import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        print(time.time() - start)        return re    return [email protected]   #==> func2 = timer(func2)def func2(a):    print('in func2 and get a:%s'%(a))    return 'fun2 over'func2('aaaaaa')print(func2('aaaaaa')) Output results :in func2 and get a:aaaaaa0.0in func2 and get a:aaaaaa0.0fun2 over
  • 4、 Multiple decorators decorate the same function

Sometimes , We will also use multiple decorators to decorate the same function .

ef wrapper1(func):   #func ----- f    def inner1():        print('wrapper1 ,before func')        func()        print('wrapper1 ,after func')    return inner1def wrapper2(func):    def inner2():        print('wrapper2 ,before func')        func()        print('wrapper2 ,after func')    return [email protected]       #f = wrapper2(f) ----->> wrapper2(inner1)  == [email protected]       #f = wrapper1(f) = innerdef f():    print('in f')f()    #===>>inner2# Multiple decorators decorate the output of the same function :wrapper2 ,before funcwrapper1 ,before funcin fwrapper1 ,after funcwrapper2 ,after func


5、 ... and 、 Decorator ——   Advanced and optimized decorator

  • 1、 Parameter decorator

The decorator above is already very beautiful 了 , But there is a problem , If I add... To countless functions in my code @timer This syntax sugar , If I don't want to use it anymore, wouldn't it be necessary for everyone to annotate it , Working day and night 3 God ? Isn't it particularly troublesome , In order to better recycle decorators when they are not in use, instead of commenting or deleting them one by one We introduce the concept of decorators with parameters

''' In order to better recycle decorators when they are not in use, instead of commenting or deleting them one by one, we introduce the concept of decorators with parameters '''import time'''FLAGE Its purpose is to use it to control the switch of the decorator , So when we don't use it, we don't need to comment one by one, just put True Change it to False Just go '''FLAGE = Truedef timmer_out(flag):    def timmer(func):        def inner(*args,**kwargs):            if flag:                start = time.time()                ret = func(*args,**kwargs)                end = time.time()                print(end - start)                return ret            else:                ret = func(*args, **kwargs)                return ret        return inner    return [email protected]_out(FLAGE)#timmer_out(FLAGE)#  It is also equivalent to executing   timmer_out(FLAGE)--->> return timmer———————>>@timmer(wahaha = timmer(wahaha))def wahaha():    time.sleep(0.1)         # If you don't rest, the function executes too fast to calculate the time     print('wahahahahahaha')wahaha()@timmer_out(FLAGE)def erguotou():    time.sleep(0.1)         # If you don't rest, the function executes too fast to calculate the time     print('erguotoutoutou')erguotou() Output results :wahahahahahaha0.10152268409729004erguotoutoutou0.10795140266418457
  • 2、 Prevent the necessary information of the function from invalidating

'''print(wahaha.__name__)      # View the function name in string format print(wahaha.__doc__)       # View the comments for a function '''# The following is used __name__ see holiday The function name of from functools import wrapsdef wrapper(func):    @wraps(func)            # Right above the innermost function     def inner(*args,**kwargs):        print(' What to do before the decorated function is executed ')        ret = func(*args,**kwargs)        print(' What to do after the decorated function is executed ')        return ret    return [email protected]        #holiday = wrapper(holiday)def holiday(day):    '''     This is a holiday notice     :param day:    :return:    '''    print(' All holidays %s God '%day)    return ' So happy 'print(holiday.__name__)print(holiday.__doc__)''' The result is inner and None  But what we want is to print holiday The string format of the function name and function comments ? The solution is   from functools import wraps Using grammar is @wraps( Decorated function name )''' Output results :holiday     This is a holiday notice     :param day:    :return:


6、 ... and 、 Decorator —— Decoration principles

  • 1、 Open and closed principle

1. The function extension of the original function is open

Why should we be open to functional extensions ?

For any program , It's impossible to have all the functions in mind at the beginning of the design without any update or modification in the future . So we have to allow later extensions 、 Add new features .

2. Closed to changes

  Why is it necessary to close the amendment ?

As we just mentioned , Because we wrote a function , It is likely that it has been imported and used elsewhere , If we change it at this time , It is likely to affect other code that is already using this function .

The decorator perfectly follows this open and closed principle . This is the original intention of learning decorators



Summary :

  • 1、 Fixed format of decorator ( Templates )

# Format 1 def timer(func):    def inner(*args,**kwargs):        ''' What to do before executing the function '''        re = func(*args,**kwargs)        ''' What to do after executing the function '''        return re    return inner# Format two from functools import wrapsdef deco(func):    @wraps(func) # Right above the innermost function     def wrapper(*args,**kwargs):        return func(*args,**kwargs)    return wrapper

About “Python How to use decorator functions ” That's all for this article , Thank you for reading ! I'm sure you're right “Python How to use decorator functions ” Knowledge has a certain understanding , If you want to learn more , Welcome to the Yisu cloud industry information channel .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved