Python之装饰器


前言

Python中的装饰器是一种高级编程技巧,它允许程序员在不修改原有代码的情况下,对函数或类进行功能的增强或修改。装饰器本质上是一个函数,它接收一个函数作为参数,并返回一个新的函数,新函数可以对原函数进行修饰。


1、需求及实现方案

1.1 需求描述

在不修改函数源码的情况下,请在以下函数执行前和执行后分别输入before和after。

def func():
    print('我是func函数')
    value = (11, 22, 33, 44)
    return value


result = func()  # 我是func函数
print(result)  # (11, 22, 33, 44)

1.2 实现方案

def func():
    print('我是func函数')
    value = (11, 22, 33, 44)
    return value

def outer(origin):
    def inner():
        print('before')
        res = origin()	# 调用原来的func函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


func = outer(func)  # 将func函数作为参数传进outer函数中,得到新的func函数【本质上是outer函数 return 的 inner】
result = func()     # 执行func函数【非原始的func函数,实质上执行inner函数】,并将结果返回给result
print(result)

输出结果:

before
我是func函数
after
(11, 22, 33, 44)

1.3 python中的@函数名

def outer(origin):
    def inner():
        print('before')
        res = origin()  # 执行原函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


"""
python中支持特殊语法,在某个函数上方使用:
@函数名
def xxx():
    pass
    
    
python内部会自动执行  函数名(xxx),执行之后,再将结果赋值给xxx,即:
xxx= 函数名(xxx)

"""


@outer
def func():
    print('我是func函数')
    value = (11, 22, 33, 44)
    return value


result = func()
print(result)

2、装饰器的应用(多个函数)

def outer(origin):
    def inner():
        print('before')
        res = origin()  # 执行原函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


@outer
def func1():
    print('我是func1函数')
    value = (11, 22, 33, 44)
    return value


@outer
def func2():
    print('我是func2函数')
    value = (11, 22, 33, 44)
    return value


@outer
def func3():
    print('我是func3函数')
    value = (11, 22, 33, 44)
    return value


func1()		# 我是func1函数
func2()		# 我是func2函数
func3()		# 我是func3函数

总结:如果对与修改的函数比较少,只是需要对函数的前后增加一部分功能,可以直接修改原函数;如果我们需要修改的原函数比较多,我们可以通过装饰器(对函数进行装饰,不改变内部结构)的方式进行增加函数功能。

3、装饰器优化支持多个参数

def outer(origin):
	# inner函数中添加参数:*args, **kwargs,支持动态参数;
    def inner(*args, **kwargs):
        print('before')
        res = origin(*args, **kwargs)  # 执行原函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


@outer
def func1(a1):
    print('我是func1函数')
    value = (11, 22, 33, 44)
    return value


@outer
def func2(a1, a2):
    print('我是func2函数')
    value = (11, 22, 33, 44)
    return value


@outer
def func3(a1, a2, a3):
    print('我是func3函数')
    value = (11, 22, 33, 44)
    return value


func1(1)
func2(1, 2)
func3(1, 2, 3)

4、装饰器知识点扩展

4.1 __name____doc__

def outer(origin):
    def inner(*args, **kwargs):
        """这是一条测试备注信息"""
        print('before')
        res = origin(*args, **kwargs)  # 执行原函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


@outer
def func1(a1):
    print('我是func1函数')
    value = (11, 22, 33, 44)
    return value


# 没有用装饰器
# print('没有用装饰器:', func1.__name__)  # 没有用装饰器: func1
# print('没有用装饰器:', func1.__doc__)  # 没有用装饰器: None

# 用了装饰器后
print('用装饰器后:', func1.__name__)  # 用装饰器后: inner
print('用装饰器后:', func1.__doc__)  # 用装饰器后: 这是一条测试备注信息

4.2 functools在装饰器中的应用

import functools

# 模版代码,务必记住
def outer(origin):
    @functools.wraps(origin)    # inner.__name__ = origin.__name__      inner.__doc__ = origin.__doc__
    def inner(*args, **kwargs):
        """这是一条测试备注信息"""
        print('before')
        res = origin(*args, **kwargs)  # 执行原函数
        print('after')
        return res

    return inner  # 注意,inner后没有括号


@outer
def func1(a1):
    """我用了functools"""
    print('我是func1函数')
    value = (11, 22, 33, 44)
    return value


# 用了装饰器后
print('用装饰器后:', func1.__name__)  # 用装饰器后: func1
print('用装饰器后:', func1.__doc__)  # 用装饰器后: 我用了functools

5 总结

  • 实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数;
  • 实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能;
  • 适用场景:多个函数系统统一在 执行前、执行后自定义一些功能;
  • 示例模版代码详见4.2。
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值