Python's path-decorator

Source: Internet
Author: User
Tags closure wrapper

As a python developer that writes functions, we are going to work from the company starting today. Write a function and give it to other developers.

Def func1 ():    print (' in func1 ')

At the end of the quarter, the company's leadership to give everyone a performance bonus, on the proposed period of time to review the results of all development, audit standards are? is to count the execution time of each function.

What are you going to do at this time?

You think, this is good, change the function:

Import Timedef func1 ():    start = Time.time ()    print (' in func1 ')    print (Time.time ()-start) func1 ()

To the company for half a year, wrote a 2000+ function, one after another, 1 weeks passed, and so the leadership audit, and then one by one to delete ... Another week has passed. Is that disturbing?

Do you think that you can not make yourself a bother to tell all the development, and now you are in your original code to add a sentence to calculate the time?

Import Timedef func1 ():    print (' in func1 ') start = Time.time () func1 () print (Time.time ()-start)

Or not, because this is too much trouble for the development of colleagues.

What about that? You brainwave, wrote a timer function ...

Import timedef Timer (func):    start = Time.time ()    func ()    print (Time.time ()-start) def func1 ():    print (' In Func1 ') def func2 ():    print (' in Func2 ') timer (func1) timer (FUNC2)

Does that look a lot easier? No matter how many functions we write, we can call this timing function to calculate the execution time of the function ... Although the modification cost has become very small, but for colleagues to change the function of the call, if a colleague because believe you, in his code to use your method 2w times, then he modified the code of your friendship boat will be completely overturned.

All you have to do is get your coworkers to call func1, but the effect of calling the timer method can be achieved.

Import timedef Timer (func):    start = Time.time ()    func ()    print (Time.time ()-start) def func1 ():    Print (' in func1 ') func1 =timer  #要是能这样的就完美了 ... Unfortunately error func1 ()

Unfortunately, the above code will be error, because the timer method needs to pass a func parameter, we can not pass the argument when the assignment, because as long as the execution of func1 = Timer (func1), the timer method is executed directly, the following sentence func1 there is no meaning. Here, our thinking seems to be in a stalemate ...

Back to Top

The forming process of the adorner

Import Timedef func1 ():    print (' in func1 ') def timer (func):    def inner ():        start = Time.time ()        func ()        print (Time.time ()-start)    return innerfunc1 = Timer (func1) func1 ()

Busy so half a day, finally take shape! It's pretty much perfect now, and the only thing that's going to be an eyesore is making an assignment call ...

You feel an eyesore, Python developers also feel an eyesore, so give us a syntax sugar to solve this problem!

Import timedef Timer (func):    def inner ():        start = Time.time ()        func ()        print (Time.time ()-start)    return inner@timer   #==> func1 = Timer (func1) def func1 ():    print (' in func1 ') func1 ()

Here, we can summarize briefly:

The essence of an adorner: a closure function

The function of the adorner: the function of the original function is extended without modifying the original function and its calling mode

There is one last question to be solved, the adorner we discussed just now is a function decorated without parameters, so what about decorating a function with parameters?

def timer (func):    def Inner (a):        start = Time.time ()        func (a)        print (Time.time ()-start)    return Inner@timerdef Func1 (a):    print (a) func1 (1)

In fact, the function of decorating with parameters is not difficult, but if you have two functions, you need to pass the parameters are different?

Import timedef Timer (func):    def Inner (*args,**kwargs):        start = Time.time ()        re = func (*args,**kwargs)        Print (Time.time ()-start)        return re    return inner@timer   #==> 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 '))

The problem with parameters is now perfectly solved, but what if your function has a return value?

Import timedef Timer (func):    def Inner (*args,**kwargs):        start = Time.time ()        re = func (*args,**kwargs)        print (Time.time ()-start)        return re    return inner@timer   #==> func2 = Timer (FUNC2) def Func2 (a):    print (' In Func2 and get a:%s '% (a))    Return ' fun2 over ' func2 (' aaaaaa ') print (Func2 (' aaaaaa '))

That decorator was perfect, but it's normal. The way we look at some of the information in a function here will expire.

def index ():    ' This is a page info '    print (' from index ') print (index.__doc__)    #查看函数注释的方法print (index.__name__)   #查看函数名的方法

To keep them from failing, let's add a little to the decorator to refine it:

From Functools import wrapsdef Deco (func):    @wraps (func) #加在最内层函数正上方    def wrapper (*args,**kwargs):        return Func (*args,**kwargs)    return Wrapper@decodef index ():    ' haha ' '    print (' from index ') print (Index.__doc __) print (index.__name__)

Back to Top

Open Closure principle

1. Open for expansion

Why open to extensions?

We say that no one program can have all the features in mind at the beginning of the design and will not make any updates or changes in the future. So we have to allow code extensions, add new features.

2. The modification is closed

Why should we be closed to the changes?

As we have just mentioned, as we write a function that is likely to have been delivered to someone else, if we modify it at this time, it is likely to affect other users who are already using the function.

The adorner perfectly follows this open closure principle.

Back to Top

The main function of the adorner and the fixed structure of the adorner

The main functions of the adorner:

The function is added before and after the function without changing the method of function invocation.

Fixed format for adorners:

def timer (func):    def Inner (*args,**kwargs): "'        re = func (*args,**kwargs)        ' after executing function before executing function '        return re    return inner
From Functools import wrapsdef Deco (func):    @wraps (func) #加在最内层函数正上方    def wrapper (*args,**kwargs):        return func (*args,**kwargs)    return wrapper

Back to Top

Adorner with parameters

If you have thousands of functions using an adorner, now you want to cancel out these adorners, what are you going to do?

A one-off? Day and night busy 3 days ...

After two days your leadership figured out, and then let you add ...

def outer (flag):    def timer (func):        def Inner (*args,**kwargs):            if flag:                print ("' before executing function")            Re = func (*args,**kwargs)            if flag:                print ("' after executing function")            return re        return inner    return Timer@outer (False) def func ():    print (111) func ()

Back to Top

Multiple adorners decorate the same function

In some cases, we also use multiple adorners to decorate the same function.

def wrapper1 (func):    def inner ():        print (' Wrapper1, before Func ')        func (        ' Wrapper1, after Func ')    return innerdef Wrapper2 (func):    def inner ():        print (' Wrapper2, before Func ')        func ()        print (' Wrapper2, after Func ')    return inner@wrapper2@wrapper1def F ():    print (' in F ') F ()

Python's path-decorator

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.