Python装饰器简单讲解

python装饰器本质上就是闭包。所谓闭包,指的是这样一类函数,其返回值是定义在其内部的另一个函数,如下例:

def outer(a):
    # 定义一个内函数inner
    def inner(b=10):
        #在内函数中 用到了外函数的临时变量a
        print('a + b = ',a+b)
        return a+b
    # 外函数的返回值是内函数的引用
    return inner

 对于一个具有装饰功能的闭包函数,假设仍取名为outer,其参数a应该被理解为一个函数对象,也就是待装饰的目标函数,为了便于理解,修改上面的代码如下:

def f1(c=0):
    print('the value is ',c)
    
def outer(func):
    a1=1
    # 定义一个内函数inner
    def inner(b=10):
        # 这个func就是要装饰的目标函数,outer函数内部并没有对它做修改
        # 只是将之放到了outer函数内部执行而已
        func()
        print('a1 + b = ',a1+b)
        return a1+b
    # 外函数的返回值是内函数的引用
    return inner

f2 = outer(f1)
f2()
#输出结果为
>>>the value is  0
>>>a1 + b =  11

要装饰的目标函数也可以先引用后定义,如上事实上已经实现了一个装饰器函数的功能,现加入语法糖@对其进行改造:

def outer(func):
    a1=1
    # 定义一个内函数inner
    def inner(b=10):
        # 这个func就是要装饰的目标函数,outer函数内部并没有对它做修改
        # 只是将之放到了outer函数内部执行而已
        func()
        print('a1 + b = ',a1+b)
        return a1+b
    # 外函数的返回值是内函数的引用
    return inner

@outer
def f1(c=0):
    print('the value is ',c)

f1()
#输出结果为
>>>the value is  0
>>>a1 + b =  11

如上就是装饰器的工作原理,此时如果去查f1函数的名称,会发现它已经不是它本身了:

f1.__name__
# 输出结果为
>>>inner

如果不做处理,以后调用f1函数,实际上就是调用定义在outer里面的inner函数,为了能够使f1函数仍旧保持其独立性,可以引入functools 的@wraps:

from functools import wraps
def outer(func):
    a1=1
    # wraps本身也是一个装饰器,提供拷贝功能
    @wraps(func)
    def inner(b=10):
        # 这个func就是要装饰的目标函数,outer函数内部并没有对它做修改
        # 只是将之放到了outer函数内部执行而已
        func()
        print('a1 + b = ',a1+b)
        return a1+b
    # 外函数的返回值是内函数的引用
    return inner

@outer
def f1(c=0):
    print('the value is ',c)

f1()
#输出结果为
>>>the value is  0
>>>a1 + b =  11
f1.__name__
# 输出结果为
>>>f1

所谓带参数的装饰器,则是在闭包上再加一层闭包:

def outer2(d):
    def outer1(func):
        a1=1
        # wraps本身也是一个装饰器
        @wraps(func)
        def inner(b=10):
            # 这个func就是要装饰的目标函数,outer函数内部并没有对它做修改
            # 只是将之放到了outer函数内部执行而已
            func(d)
            print('a1 + b = ',a1+b)
            return a1+b
        # 外函数的返回值是内函数的引用
        return inner
    return outer1


@outer2(100)
def f1(c):
    print('the value is ',c)
f1(1)

至于通过类来实现装饰功能,待以后有时间再整理更新。感谢阅读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值