zoukankan      html  css  js  c++  java
  • Python装饰器--decorator

    装饰器

    装饰器实质是一个函数,其作用就是在不改动其它函数代码的情况下,增加一些功能。
    如果我们需要打印函数调用前后日志,可以这么做
    def log(func):
        print('%s is running' % func.__name__)
        func()
    
    def bar():
        print('bar')
    #将bar作为函数log参数传入
    >>>log(bar)
    bar is running
    bar

    这样写下来一个函数打印一个函数的日志是没有问题的,但是很多呢?

    def log(func)
        def wrapper(*args,**kw):
            print('%s',%func.__name__)
            return func(*args,**kw)
        return wrapper
    
    
    def bar():
        print('bar')
    
    bar
    = log(bar) bar()

    借助decorator的语法糖,一个@就可以解决

    def log(func):
        def wrapper(*args,**kw):
            print('call %s()' %func.__name__)
            return func(*args,**kw)
        return wrapper
    
    @log   #相当于bar = log(bar)
    def bar():
        print('this is bar')
    
    @log
    def bar2():
        print('this is bar2')
    装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

    装饰器是允许带参数的,装饰器的语法可以使我们在调用时,提供其他参数。

    import functools
    def log(level):
        def decorator(func):
            #@functools.wraps(func)  #这里先注释一下
            def wrapper(*args,**kw):
                print('%s %s()'% (level,func.__name__))
                return func(*args,**kw)
            return wrapper
        return decorator
    @log('execute')
    def bar():
        print('bar')
    
    >>>bar()
    execute bar()
    bar

    >>>print(bar.__name__)
    wrapper

    这里的@log('execute')相当于    bar = log('execute')(bar)

    函数对象可以通过__name__属性拿到名称

    bar.__name__  拿到的是wrapper,这是因为bar函数经过装饰器装饰之后,最终返回了wrapper函数

     

    如果不更改bar.__name__的属性,在一些依赖函数签名的代码中就会出错

    Python自带的functools.wraps就是将原始函数__name__赋值给wrapper

    import functools
    def log(level):
        def decorator(func):
            @functools.wraps(func)  #这里删除注释
            def wrapper(*args,**kw):
                print('%s %s()'% (level,func.__name__))
                return func(*args,**kw)
            return wrapper
        return decorator
    @log('execute')
    def bar():
        print('bar')
    
    >>>bar()
    execute bar()
    bar
    
    >>>print(bar.__name__)
    bar   #__name__还原成了bar

     

    类的装饰器

     

     

     

     

     

     

    参考链接知乎--Python装饰器

     

  • 相关阅读:
    C++中整型变量的存储大小和范围
    A1038 Recover the Smallest Number (30 分)
    A1067 Sort with Swap(0, i) (25 分)
    A1037 Magic Coupon (25 分)
    A1033 To Fill or Not to Fill (25 分)
    A1070 Mooncake (25 分)
    js 获取控件
    C#代码对SQL数据库添加表或者视图
    JS 动态操作表格
    jQuery取得下拉框选择的文本与值
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7643216.html
Copyright © 2011-2022 走看看