python装饰器

作者: dpengwang | 来源:发表于2018-05-18 16:08 被阅读49次

    python装饰器是一个以函数作为参数并返回一个替换函数的可执行函数,在不改变函数源码的情况下为函数增添一些新功能

    函数装饰器

    不带参数的装饰器

    python接收函数返回函数实现:

    def outer(func):
       def innner():
           print("before func")
           ret =func()
           return ret+1
       return innner
    def func():
       return 1
    
    newfunc =  outer(func)
    print(newfunc())
    

    ==>

    2
    

    newfunc()就是func函数的装饰版本,注意写这种闭包函数的时候函数是否加( )(即是调用函数引用还是函数执行的问题)

    利用@语法糖形式

    def outer(func):
        def innner():
            print("before func")
            ret =func()
            return  ret+1
        return innner
    @outer
    def func():
        return 1
    func()
    
    2
    
    带参数的装饰器

    上面的装饰器中,装饰器的唯一参数就是在执行业务的参数,装饰器的允许我们在调用时,提供其他参数,这样就为装饰器的编写和使用提供了更大的灵活性

    不带参数的装饰器一般有两层,带参数的装饰器一般三层(我认为的),最内层返回原函数的调用,@得到装饰后的函数,调用的时候将返回的方法执行出来

    import logging
    def use_logging(level):
        def decrator(func):
            def wrapper():
                if level=="warn":
                    logging.warn("this is warning")
                return func()
            return wrapper
        return decrator
    @use_logging(level="warn")
    def f():
        print("hello")
    f()
    

    不用语法糖的形式是:

    func=use_logging(level="warn")(foo)
    f()
    

    ps:才知道竟然可以这样给嵌套函数传递参数TT

    类装饰器

    写一个类,里面实现initcall方法,call方法会别自动装饰在目标函数上,在使用@语法糖的时候,以@类名()的形式,而装饰器函数时@func的形式

    class logged(object):
        def __init__(self):
            pass
    
        def __call__(self, func):
            def wrapped_function():
                print("decorator has run")
                return func()
            return wrapped_function
    
    
    @logged()
    def f():
        print("hello")
    f()
    

    ==>

    decorator has run
    hello
    

    装饰器的缺点

    会使原函数的元信息被装饰器的信息覆盖,比如函数的_name_

    def loggeg(func):
        def with_logging(*args):
            print(func.__name__+" is calling")
            return  func(*args)
        return  with_logging
    @loggeg
    def f():
        print("hello")
    
    print(f.__name__)
    

    ==>

    with_logging
    

    不加装饰器的时候输出的是f

    用functools.wraps可以将原函数的元信息拷贝到装饰器函数中,这样就能让装饰器函数和原函数有一样的元信息了

    from functools import  wraps
    def loggeg(func):
        @wraps(func)#注意要传入func
        def with_logging(*args):
            print(func.__name__+" is calling")
            return  func(*args)
        return  with_logging
    @loggeg
    def f():
        print("hello")
    
    print(f.__name__)
    

    ==>

    f
    

    相关文章

      网友评论

      本文标题:python装饰器

      本文链接:https://www.haomeiwen.com/subject/psigdftx.html