装饰器

一 闭包:函数作参数,返回值,嵌套函数

(https://www.runoob.com/w3cnote/python-func-decorators.html)

装饰器

import functools

定义一个装饰器log
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("I'm a param")


运行结果
call test():
args = I'm a param
test param: I'm a param

实际上是test做log的参数,即@语法将函数test传入装饰器函数log,
先调用log(test),返回函数wrapper
再显示执行wrapper("I'm a param"),执行两个print,返回并执行函数test("I'm a param")  

注意哈wrapper里面是return func(*args, **kwargs)不是return func,
因此不同于log里面return wrapper;log返回后wrapper还需要显示调用wrapper("I'm a param"),
而test不需要了直接执行test函数

因此上述调用方式等价于下面这种写法
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


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


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

因此装饰器在使用时,用了@语法,让人有些困扰。其实,装饰器只是个方法
@语法只是将函数传入装饰器函数,并无神奇之处。

值得注意的是@functools.wraps(func),这是python提供的装饰器。
它能把原函数test的元信息test.name拷贝到装饰器log里面的 func 函数func.name中。函数的元信息包括docstring、name、参数列表等等。
可以尝试去除@functools.wraps(func),会发现test.__name__的输出变成了wrapper。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值