专题:函数装饰器

1、定义:在不改变原函数的调用以及内部代码的情况下,为其添加新功能的函数。

 

 

 2、装饰器的逻辑推导

def func01():
    print("func01执行了")

def print_func_name(func):
    def wrapper():
        # 新功能
        print(func.__name__)
        # 旧功能
        func()
    return wrapper

func01 = print_func_name(func01)  # 此时:func01==wrapper
func01()  # 执行的是内部函数wrapper()

# 输出:
func01
func01执行了

当函数func01()有返回值时:

def func01():
    print("func01执行了")
    return "ok"

def print_func_name(func):
    def wrapper():
        # 新功能
        print(func.__name__)
        # 旧功能
        func()
    return wrapper


func01 = print_func_name(func01)   # 此时,func01==wrapper
func01()  # 执行的是内部函数wrapper()
print(func01())   # 即:print(wrapper()),而wrapper没有返回值,所以下面输出最后返回None

# 输出:
func01
func01执行了
None

上面代码中,由于我们写了func01=print_func_name(func01),而print_func_name的返回值是wrapper,所以func01==wrapper,我们在调用func01()时,其实调用的是wrapper()了,不再是顶上的func01(),它等于是被拦截了(装饰器的核心思想就是拦截),而wrapper函数没有返回值,所以输出为None。如果想输出ok,应该把wrapper函数中的func()改为return func()。代码如下:

def func01():
    print("func01执行了")
    return "ok"

def print_func_name(func):
    def wrapper():
        # 新功能
        print(func.__name__)
        # 旧功能
        return func()
    return wrapper


func01 = print_func_name(func01)   # 即:func01==wrapper,因为print_func_name返回值是wrapper
func01()  # 即:执行wrapper(),执行print(func.__name__)
print(func01())   # 相当于print(wrapper()),即:print(func01()旧功能),故输出ok

# 输出:
func01
func01执行了
ok

当有func01()和func02()两个函数时,且func2()有参数,而func01()没有参数:

最后,光有*args还不够,因为*args只能搞定位置实参,还要有**kwargs来搞定关键字实参。下面的代码就是完整的装饰器推导了

练习:在不改变原有功能的定义与调用情况下(进入后台,删除订单),为其增加新功能(验证权限)

def enter_background():
    print("进入后台")

def delete_order():
    print("删除订单")

def verify_permissions(func):
    def wrapper(*args, **kwargs):
        # 新功能
        print("验证权限")
        # 旧功能
        return func(*args, **kwargs)
    return wrapper

enter_background = verify_permissions(enter_background)
enter_background()
delete_order = verify_permissions(delete_order)
delete_order()

# 输出:
验证权限
进入后台
验证权限
删除订单

 以上只是装饰器的推导原理,在真实的Python中,装饰器不是像上面这样写的,应该是这样:

def print_func_name(func):
    def wrapper(*args, **kwargs):
        # 新功能
        print(func.__name__)
        # 旧功能
        return func(*args, **kwargs)
    return wrapper

@print_func_name    # 内部原理其实就是:func01 = print_func_name(func01)
def func01():
    print("func01执行了")
    return "ok"

@print_func_name    # 内部原理其实就是:func02 = print_func_name(func02)
def func02(a):
    print(a, "func02执行了")


# func01 = print_func_name(func01)  # 不需要了
print(func01())
# func02 = print_func_name(func02)  # 不需要了
print(func02(100))

 装饰器的作用:

可能一个函数我们今天想给它增加一个功能A,但是明天我们想把功能A给换成功能B,那么如果把这些新增的功能直接写在函数内然后再改来改去就很麻烦,所以我们可以用装饰器来完成这些操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值