Python装饰器(语法糖)

1、反面教材

# TODO make an order 
def ordering():
    # 第一验证 验证是否登录
    # 第二验证 验证是否具有权限
    print('————————正在下订单————————')


# TODO change password
def changepwd():
    # 第一验证 验证是否登录
    # 第二验证 验证是否具有权限
    print('————————修改密码————————')

# TODO show your personal info
def showinfo():
    # 第一验证 验证是否登录
    # 第二验证 验证是否具有权限
    print('————————个人信息————————')

可以看到我们在进行下订单,修改密码或是查询自己的信息时都需要在登录,并且具有相应权限的情况下进行。
但是我们不可能在每个函数里都写这样的两个函数。因为代码会变得冗余。
所以这里就用到了装饰器但装饰器是基于闭包的。所以先来了解闭包。

2、闭包(提高函数的重用性)

一个函数嵌套另一个函数,内部的函数使用到了外部的函数的变量

def wrapper(num1):
    def inner(num2):
        return num1 + num2

    return inner


if __name__ == '__main__':
    func = wrapper(1)
    print(func(2))

打印输出:3

闭包实现一个二元一次直线方程

def wrapper(k,b):
    def inner(x):
        return x*k + b
    return inner


if __name__ == '__main__':
    func = wrapper(1,1)
    print(func(2))

打印输出:3

缺点:一直引用外部函数的变量而不释放,容易消耗内存

3、正面教材

3.1 方法一:

def wrapper(func):      # func被装饰的函数的引用
    def inner():
        # 第一验证 验证是否登录
        # 第二验证 验证是否具有权限
        print("我是装饰器")
        func()          # 调用函数
    return inner        # 不带括号,因为返回函数的引用,而不是调用函数


def changepwd():
    print('————————修改密码————————')


if __name__ == '__main__':
    MyFunc = wrapper(changepwd)   # 引用
    MyFunc()
 

输出打印:我是装饰器
————————修改密码————————

3.2 方法二:

def wrapper(func):      # func被装饰的函数的引用
    def inner():
        # 第一验证 验证是否登录
        # 第二验证 验证是否具有权限
        print("我是装饰器")
        func()          # 调用函数
    return inner        # 不带括号,因为返回函数的引用,而不是调用函数


@wrapper
def changepwd():
    print('————————修改密码————————')


if __name__ == '__main__':
    changepwd()

打印输出:我是装饰器
————————修改密码————————

给函数添加上了@wrapper,使得函数具备新的功能。

3.3 多层包裹

def wrapper1(func):       # func被装饰的函数的引用
    print('begin wrapper1')
    
    def inner():             # 调用参数用inner
        print(1)
        func()

    print('end wrapper1')
    return inner


def wrapper2(func):
    print('begin wrapper2')
    
    def inner():
        print(2)           # print要写在func()之前!!!
        func()

    print('end wrapper2')
    return inner


@wrapper2
@wrapper1      # 结合性自下而上,执行性自上而下
def changepwd():
    print('--------修改密码-----------')

直接执行,不调用,可以看到
begin wrapper1
end wrapper1
begin wrapper2
end wrapper2
wrapper1先,这就是装饰的结合性,自下而上

if __name__ == '__main__':
    changepwd()

加上执行,可以看到
begin wrapper1
end wrapper1
begin wrapper2
end wrapper2
2
1
--------修改密码-----------
先执行wrapper2,这就是执行性,自上而下

3.4 带参数的函数装饰

def wrapper(func):         # 装饰器要写在函数上面,函数才能使用
    def inner(*args):
        func(args[0],args[1])
        print("{}块钱用完了,蛋糕还不好吃……{}".format(args[0],args[1]))
    return inner

@wrapper
def cost(money,status):
    print("买买买了%d块钱的蛋糕"%money)


if __name__ == '__main__':
    cost(10,"不开心不开心呢")

3.4 装饰工厂

三层嵌套

def create():
    def wrapper(func):
        def inner():
            func()
        return inner
    return wrapper
==========三层可实现装饰器带参数=======
def create(arg1, arg2):
    def wrapper(func):
        def inner(x):
            func(x)
            print(arg1, arg2)
            return 4
        return inner
    return wrapper


@create(5, 6)
def calc(x):
    print('ok%s'%x)

ret = calc(3)


print(ret)
ok3
5 6
4

4、总结:

装饰器的应用场景:
1.减少冗余代码,提高函数的重用性
2.增加额外功能
缺点:一直引用外部函数的变量而不释放,容易消耗内存

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值