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

     

  • 相关阅读:
    httpclient之基本类
    安卓开发遇到的各种问题
    C#获取字符串宽度像素
    Android开发参考资料
    Windows Phone开发参考资料
    Windows Phone锁屏背景相关代码
    Windows Phone Launcher class
    Windows Phone SplashScreen初始屏幕示例
    ASP如何实现注册后发送激活邮件?
    SkyDrive开发申请ClientID
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7643216.html
Copyright © 2011-2022 走看看