python装饰器,懂了这篇够用

1.装饰器本质是一个函数,该函数的参数是另一个函数。目的增加函数的功能。

2.@语法只是将函数传入装饰器函数,并无神奇之处。

一、带参数的装饰器(函数)

特点两层函数

import functools


def log(func):                         #第一层
    @functools.wraps(func)             #为了解决被装饰函数的名称变化的问题
    def wrapper(*args, **kwargs):      #第一层
        print('call %s():' % func.__name__)
        print('args = {}'.format(*args))
        return func(*args, **kwargs)

    return wrapper

使用装饰器有两种方式,第一种也就加一个@符号就用了。第二种就是两次调用。

@log
def test(p):
    print(test.__name__ + " param: " + p)
def test(p):
    print(test.__name__ + " param: " + p)

wrapper = log(test)
wrapper("I'm a param")

 

二、带参数的装饰器 (函数)

特点 是三层函数,为啥三层,因为要传除了被装饰的func函数外,还要传其他参数。

import functools

def log_with_param(text):                # 第一层
    def decorator(func):                 # 第二层
        @functools.wraps(func)
        def wrapper(*args, **kwargs):    # 第三层
            print('call %s():' % func.__name__)
            print('args = {}'.format(*args))
            print('log_param = {}'.format(text))
            return func(*args, **kwargs)

        return wrapper

    return decorator
    
@log_with_param("param")
def test_with_param(p):
    print(test_with_param.__name__)

理解:

decorator = log_with_param("param")

wrapper = decorator(test_with_param)

wrapper('实际的参数')

使用

test_with_param('实际的参数')  #加了装饰器的函数,调用还是一样调用,但是该函数增加了装饰器 的功能

附上完整的两个例子

import functools


def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('call %s():' % func.__name__)
        print('args = {}'.format(*args))
        return func(*args, **kwargs)

    return wrapper
@log
def test(p):
    print(test.__name__ + " param: " + p)
    
test("实际参数")


# 运行信息如下:
"""
call test():
args = 实际参数
test param: 实际参数
"""

 

import functools
def log(text):
    print(text)
    def decorator(func):
         @functools.wraps(func)
         def wrapper(*args,**kwargs):
                 res = func(*args,**kwargs)
                 return res
         return wrapper
    
    return decorator



@log('装饰器参数')
def test(text):
    print(text)

#调用
test('我是被装饰器的函数的参数')

三、多层装饰器 

def first_decorator(func):
    print('--first--')

    def first_wrapper(*args, **kwargs):
        print('------first---%s---' % func.__name__)
        return func(*args, **kwargs)
    return first_wrapper


def second_decorator(func):
    print('--second--')

    def second_wrapper(*args, **kwargs):
        print('------second---%s---' % func.__name__)
        return func(*args, **kwargs)
    return second_wrapper

@first_decorator
@second_decorator
def test_func_1():
    print('excute %s' % inspect.stack()[0][3])
def timeit(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        ret = func(*args, **kwargs)
        cost = time.time() - start
        print("cost %f second " % cost)
        return ret
    return wrapper


def delay(sec):
    def wrapper(func):
        def _wrapper(*args, **kwargs):
            time.sleep(sec)
            ret = func(*args, **kwargs)
            print("delay %d seconds to call %s" % (sec, func.__name__))
            return ret
        return _wrapper
    return wrapper


@timeit
@delay(2)
def add(a, b):
    return a + b


if __name__ == "__main__":
    add(1, 2)

"""
delay 1 seconds to call add
cost 2 second
"""

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章