Python 装饰器

"""
开放封闭原则:
开放:对代码的拓展是开放的
封闭:对源码的修改是封闭的

装饰器:
    装饰器本身就是一个函数,装饰器的本质是闭包。装饰器遵循开放封闭原则。
    装饰器装饰一个函数时,在不改变原函数的源码以及调用方式的前提下,给原函数增加额外的新功能
"""
import time


# 1、原始版装饰器


def login_csdn():
    time.sleep(2)
    print('欢迎登录CSDN社区')


def time_test(func):  # func = login_csdn函数的地址
    """测试登录csdn社区函数的执行效率"""

    def inner():
        start_time = time.time()
        func()  # login_csdn()  这里是闭包,内层函数对外层函数非全局变量的引用
        end_time = time.time()
        print(f'该函数执行效率为:{end_time - start_time}')

    return inner


login_csdn = time_test(login_csdn)  # 左边login_csdn变量得到的是 inner函数的内存地址
login_csdn()  # inner()


# 2、标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (此版本被装饰函数无返回值,但是有返回值被装饰函数却不能得到返回值,不完美)

def time_test(func):  # func = login_csdn函数的地址
    """测试登录csdn社区函数的执行效率"""

    def inner():
        start_time = time.time()
        func()  # login_csdn()  这里是闭包,内层函数对外层函数非全局变量的引用
        end_time = time.time()
        print(f'该函数执行效率为:{end_time - start_time}')

    return inner


# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn():
    time.sleep(2)
    print('欢迎登录CSDN社区')


login_csdn()


# 3、标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (被装饰函数具有返回值)

def time_test(func):  # func = login_csdn函数的地址
    """测试登录csdn社区函数的执行效率"""

    def inner():
        start_time = time.time()
        res_return = func()  # login_csdn()  这里是闭包,内层函数对外层函数非全局变量的引用
        end_time = time.time()
        print(f'该函数执行效率为:{end_time - start_time}')
        return res_return

    return inner


# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn():
    time.sleep(2)
    print('欢迎登录CSDN社区')
    return '777 我要返回一些数据'


# ret 实际接收的是内层函数inner的返回值,但是被装饰函数的返回值是给了装饰器里面func()函数这个执行者
# 所以内层函数的返回值只需要返回func()函数的执行者,即res_return
ret = login_csdn()
print(ret)


# 4、最标准版装饰器: 装饰器函数要写在所有被装饰函数的最上面 (被装饰函数具有返回值,被装饰函数含有参数)

def time_test(func):  # func = login_csdn函数的地址
    """测试登录csdn社区函数的执行效率"""

    def inner(*args, **kwargs):  # 函数定义,*代表聚合
        start_time = time.time()
        # 函数调用,*代表打散, func(*('苏秦', 17)) == func('苏秦', 17) == login_csdn('苏秦', 17)
        res_return = func(*args, **kwargs)  # login_csdn()  这里是闭包,内层函数对外层函数非全局变量的引用。
        end_time = time.time()
        print(f'该函数执行效率为:{end_time - start_time}')
        return res_return

    return inner


# @time_test叫语法糖,相当于这句 login_csdn = time_test(login_csdn)。
# 代码执行到“@time_test”这行时,会同时执行下面“def login_csdn():”这行,
# 拿到函数名的地址,然后执行login_csdn = time_test(login_csdn)这句代码,把函数名地址传给装饰器函数time_test
@time_test
def login_csdn(name, age):
    time.sleep(2)
    print(f'欢迎{name}登录CSDN社区, 今年{age}岁!!!')
    return '777 我要返回一些数据'


# ret 实际接收的是内层函数inner的返回值,但是被装饰函数的返回值是给了装饰器里面func()函数这个执行者
# 所以内层函数的返回值只需要返回func()函数的执行者,即res_return
ret = login_csdn('苏秦', 17)
print(ret)

# 5、最终标准版装饰器模板
def wrapper(func):
    def inner(*args, **kwargs):
        """
        这里添加:
        执行被装饰函数之前的操作
        """
        ret = func(*args, **kwargs)
        """
        这里添加:
        执行被装饰函数之后的操作
        """
        return ret
    return inner

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值