Iron Music Learning python_day12_ Decorative Device

Source: Internet
Author: User
Tags closure wrapper

"Useful information for functions"
例:def login(user, pwd):    ‘‘‘    功能:登录调用    参数:分别有user和pwd,作用分别是用户和密码;    return: 返回值是登录成功与否(True,False)    ‘‘‘    print"欢迎登录")print(login.__name__#查看函数名字print(login.__doc__)  #查看函数注释login    功能:登录调用    参数:分别有user和pwd,作用分别是用户和密码;    return: 返回值是登录成功与否(True,False)

The name of the function. __name__ this is the way to see the names of the functions
The function name. __doc__ This is the way to see the comment

The above two methods are useful in the Operation audit log, with the use of adorners can record a lot of information.
But when used in a function decorated by a decorator, it becomes the function name and comment of the adorner,
Therefore, it is necessary to use the wraps module to implement the display name and annotation is still the original function of decoration.

Cases:

fromimport wraps# 函数工具库的warps模块来实现装饰器函数名字仍是被装饰的原函数名字def deco(func):    @wraps#加在最内层函数正上方    def wrapper(***kwargs):        return func(***kwargs)    return wrapper@decodef index():    ‘‘‘首页的注释‘‘‘    print(‘from index‘)print(index.__doc__)print(index.__name__)首页的注释index
"Adorner Decorator"

The adorner is essentially a Python function that allows other functions to add additional functionality without any code changes, and the return value of the adorner is also a function object.
Application scenarios for adorners: such as inserting logs, performance tests, transaction processing, caching, and so on.

The grammatical sugar of the adorner: @ immediately following the function name of the adorner, placed above the function that needs to be decorated.
Because the image of @ is very much like a sweet one-round lollipop, so it is a nickname for the grammatical sugar.
It is much more flexible and elegant to have a function name that is directly stiff and will be decorated with the function name of the adorner.
Even if the change is not too much trouble.

Example: Here is a decorator that prints GMT at the time the function is called:ImportTime# Introducing Time ModulesdefWrapper (func):" "This adorner is primarily used to test the working time of the decorated function" "    defInner*Args**Kwargs): start_time=Time.time () ret=Func*Args**Kwargs) Time.sleep (0.2322)# Elapsed time after the simulation function was executedEnd_time=Time.time () Sec=End_time-Start_timePrint(' This program execution time is%s' % round(sec,5))returnRet# is equivalent to returning func ()    returnInner@wrapper # syntax sugar decoration on the after, equivalent is to be below the Hello = wrapper (hello)defHello ():Print(' hero say hello ') Hello ()# is equivalent to executing wrapper (hello) (), which is equivalent to executing the inner function body in the wrapper layer. # So the additional functionality is performed, and the function is called normally. # Execution effect is as follows:Hero say hello this program execution time is0.23301The above example is a nested adorner, which is relatively simple. Because we have a dynamic parameter set in the inner function of the inner layer (*Args and**Kwargs) The decorated function has the ability to set parameters, it can also be passed normally, such as:@wrapper # syntax sugar decoration on the after, equivalent is to be below the Hello = wrapper (hello)defHello (name):Print(' hero say hello%s' %Name) Hello (' Tiele ')# is equivalent to executing wrapper (hello) (), which is equivalent to executing the inner function body in the wrapper layer. # So the additional functionality is performed, and the function is called normally. return: Hero Say hello Tiele this program execution time is0.23301But one thing to note is that after decorator decorated functions, their __name__ have been from the original' function name 'Become a' inner ':Print(hello.)__name__) Hero Say hello Tiele this program execution time is0.23301Inner because looking directly at the function name and comment method to see the function that has been decorated by the adorner will result in the wrong information (the name and comment of the adorner is returned), which does not meet our needs (although it is printed directly in the inner function func.__name__ You can derive the name of the original function, but use it in a global environment. __NAME__ View or error) so you have to use the Python built-in functools.wraps to support the global view of the function name when you see the correct original function name:ImportTime# Introducing Time ModulesImportFunctools# Introducing the Function tool moduledefWrapper (func):" "This adorner is primarily used to test the working time of the decorated function" "    # Add to the top of the inner function, because it's the name of the inside function    @functools. Wraps(func)defInner*Args**Kwargs): start_time=Time.time () ret=Func*Args**Kwargs) Time.sleep (0.2322)# Elapsed time after the simulation function was executedEnd_time=Time.time () Sec=End_time-Start_timePrint(' This program execution time is%s' % round(sec,5))returnRet# is equivalent to returning func ()    returnInner@wrapper # syntax sugar decoration on the after, equivalent is to be below the Hello = wrapper (hello)defHello (name):Print(' hero say hello%s' %Name) Hello (' Tiele ')# is equivalent to executing wrapper (hello) (), which is equivalent to executing the inner function body in the wrapper layer. # So the additional functionality is performed, and the function is called normally. Print(' function name is '+Hello.__name__) Hero Say hello Tiele this program execution time is0.23301Function name is Hello

As in the example above, it looks like a syntactic sugar decorator is also installed above the inner function.

"Adorner with parameters"

With parameters in the function, we are implemented. However, some situations require that the adorner itself also takes parameters to control the flow and the adorner switch, it is necessary to nest a layer of outside functions to implement.

Example: (The outer layer of this parameter is a dynamic parameter, rather than accept the decorated function name to do parameters)

 fromFunctoolsImportWraps# function Tool Library warps module to implement adorner function name is still decorated with the original function nameImportTime# Introduction Time moduledefTimer*Args**Kwargs):defWrapper (f):@wraps(f)# Add to the top of the inner function, because it's the name of the inside function        defInner*Args**Kwargs):" "This feature is used to test function start and end times:p Aram args::p Aram Kwargs:: return:" "            ifFlag:starttime=Time.time () ret=F*Args**Kwargs) Time.sleep (0.3) EndTime=Time.time () Sec=EndTime-StartTimePrint(' This program performs efficiently%f' %SecElse: RET=F*Args**Kwargs)returnRetreturnInnerreturnWrapperflag= True@timer()defHello_word ():" "say hello to the world: Return:none" "    Print(' Hello,word.hello,hero. ') Hello_word ()Print(Hello_word.__name__)Print(hello_word.__doc__) Hello,word.hello,hero. This program performs efficiently0.300017Hello_word to the world say hello:return:NoneFlag is false, and the calculation time function of the adorner will not be executed.defTimer (flag):# with flag parameter, can control the switch of the adorner    defWrapper (f):@wraps(f)# Add to the top of the inner function, because it's the name of the inside function        defInner*Args**Kwargs):" "This feature is used to test function start and end times:p Aram args::p Aram Kwargs:: return:" "            ifFlag:starttime=Time.time () ret=F*Args**Kwargs) Time.sleep (0.3) EndTime=Time.time () Sec=EndTime-StartTimePrint(' This program performs efficiently%f' %SecElse: RET=F*Args**Kwargs)returnRetreturnInnerreturnWrapper@timer(False)defHello_word ():" "say hello to the world: Return:none" "    Print(' Hello,word.hello,hero. ') Hello_word () Hello,word.hello,hero.

In the example above, when we change the value of flag to false, the adorner's extra functionality is not triggered.

"Open closure principle"

1. Open for expansion
Why open to extensions?
Any program, it is not possible at the beginning of the design has been thinking of all the features and future do not make any updates and changes.
You must allow code extensions, add new features, and so on.

2. The modification is closed
Why should we be closed to the changes?
Write a function that is likely to have been delivered to someone else, and if it is modified at this time, it is likely to affect other users who are already using the function.

The adorner perfectly follows this open closure principle.

"Multiple adorners decorate a function"

Cases:

def  Wrapper1 (func): def  inner (): print  ( ' Wrapper1, before Func ' ) Func () print  ( ' Wrapper1, after Func ' ) return
      innerdef  Wrapper2 (func): def  inner (): pri NT  ( ' Wrapper2, before Func ' ) func () print  ( ' Wrapper2, after Func ' ) return  inner @wrapper2   def  f (): print  () F () Effect: Wrapper2, before Funcwrapper1, before Funcin  Fwrapper1, after Funcwrapper2, After Func  


The rule is to execute the previous statement before the original function, then execute the original function, then the statement after the function.

End
2018-4-4

Iron Music Learning python_day12_ Decorative Device

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.