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装饰器

     

  • 相关阅读:
    自己写的一个ASP.NET服务器控件Repeater和GridView分页类
    c#Udp分包组包方法
    利用反射写的,可以插件的俄罗斯方块
    冰之随笔一(c#反射、特性)
    Socket的简单例子
    HTTP状态码
    C# WebService 基础实例
    Win7上IIS发布网站系统部署项目
    FileUpload 简单上传+小预览
    .net 验证码
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7643216.html
Copyright © 2011-2022 走看看