zoukankan      html  css  js  c++  java
  • python装饰器

    装饰器的主要功能:在不改变函数调用方式的基础上在函数的前、后添加功能 ,类似C#的AOP编程。添加功能的这部分就在装饰器中,典型的格式如下:

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner
     
    from functools import wraps
     
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper

    比如我们给fun增加一个记时的装饰器,还要考虑到函数的参数调用

    import time
     
    def timer(f):  # 装饰器函数
        def inner(*argc, **kwargc):
            start = time.time()
            ret = f(*argc, **kwargc)  # 被装饰的函数
            end = time.time()
            print(end - start)
            return ret
        return inner
     
     
    @timer  # 语法糖 @装饰器函数名,相当于调用func=timmer(func)
    def func(name):  # 紧挨着被装饰函数
        time.sleep(0.01)
        print("hello:%s" % name)
        return "first time:"+name

    运行结果如下:

    hello:gavin
    0.010966062545776367
    first time:gavin

    两个有用的宏:fun的__name__查看字符串格式的函数名,__doc__查看函数的注释

    from functools import wraps
    def wrapper(func):  #func = holiday
        @wraps(func)
        def inner(*args,**kwargs):
            print('在被装饰的函数执行之前做的事')
            ret = func(*args, **kwargs)
            print('在被装饰的函数执行之后做的事')
            return ret
        return inner
     
    @wrapper   #holiday = wrapper(holiday)
    def holiday(day):
        '''这是一个放假通知'''
        print('全体放假%s天'%day)
        return '好开心'
     
    print(holiday.__name__)
    print(holiday.__doc__)
    ret = holiday(3)   #inner
    print(ret)

    运行结果:

    holiday
    这是一个放假通知
    在被装饰的函数执行之前做的事
    全体放假3天
    在被装饰的函数执行之后做的事
    好开心
    带参数的装饰器:假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?一个一个的取消掉?

    import time
    FLAGE = False
    def 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 timmer
    # timmer = timmer_out(FLAGE)
    @timmer_out(FLAGE)    #wahaha = timmer(wahaha)
    def wahaha():
        time.sleep(0.1)
        print('wahahahahahaha')
     
    @timmer_out(True)
    def erguotou():
        time.sleep(0.1)
        print('erguotoutoutou')
     
    wahaha()
    erguotou()

    运行结果:

    wahahahahahaha
    erguotoutoutou
    0.10001111030578613

    多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner1():
            print('wrapper1 ,before func')
            ret = func()
            print('wrapper1 ,after func')
            return ret
        return inner1
     
    def wrapper2(func):
        def inner2():
            print('wrapper2 ,before func')
            ret = func()
            print('wrapper2 ,after func')
            return ret
        return inner2
     
    def wrapper3(func):
        def inner3():
            print('wrapper3 ,before func')
            ret = func()
            print('wrapper3 ,after func')
            return ret
        return inner3
     
    @wrapper3
    @wrapper2
    @wrapper1
    def f():
        print('in f')
        return '哈哈哈'
     
    print(f())

    运行结果:

    wrapper3 ,before func
    wrapper2 ,before func
    wrapper1 ,before func
    in f
    wrapper1 ,after func
    wrapper2 ,after func
    wrapper3 ,after func
    哈哈哈

    functools的wrap:Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。
    不加wraps:

    # coding=utf-8
    # -*- coding=utf-8 -*- 
    from functools import wraps
     
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            '''decorator'''
            print('Calling decorated function...')
            return func(*args, **kwargs)
        return wrapper
     
    @my_decorator
    def example():
        """Docstring"""
        print('Called example function')
     
    print(example.__name__, example.__doc__)

    运行结果是:

    wrapper decorator

    返回的值装饰器的名称和注释;加wraps:

    # coding=utf-8
    # -*- coding=utf-8 -*-
    from functools import wraps
     
    def my_decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            '''decorator'''
            print('Calling decorated function...')
            return func(*args, **kwargs)
     
        return wrapper
     
     
    @my_decorator
    def example():
        """Docstring"""
        print('Called example function')
     
    print(example.__name__, example.__doc__)

    运行结果:

    example Docstring 

    是源函数的定义和注释

  • 相关阅读:
    Android开发 ViewConfiguration View的配置信息类
    Android 开发 倒计时功能 转载
    Android 开发 关于7.0 FileUriExposedException异常 详解
    Android 开发 实现文本搜索功能
    Android 开发 Activity里获取View的宽度和高度 转载
    Android 开发 存储目录的详解
    Android 开发 Fresco框架点击小图显示全屏大图实现 ZoomableDraweeView
    Android 开发 将window变暗
    Android 开发 DisplayMetrics获取Android设备的屏幕高宽与其他信息
    Android 开发 DP、PX、SP转换详解
  • 原文地址:https://www.cnblogs.com/majiang/p/9913780.html
Copyright © 2011-2022 走看看