Python3之装饰器(Decorator)浅谈

日期:2020年2月28日
作者:Commas
注释:学习就是为了忘记,接上一章《Python3之闭包浅谈》,现在讲一下Python装饰器;
如果您想了解更多有关Python的知识,那么请点《我的Python浅谈系列目录》



一、装饰器前言

装饰器(Decorator)是一个装饰函数的函数,本质就是一个函数,用来在不修改被装饰函数的源代码与调用方式的前提下,对被装饰函数进行功能扩展的函数。掌握装饰器前需要学习以下4点知识:

  1. 函数的本质就是一个指向函数本体的内存地址,执行函数的方法为函数名()
  2. 闭包(closure)知识;
  3. 开放封闭原则(OCP,Open Closed Principle):对扩展是开放的,而对修改是封闭的;
  4. 函数的元组参数(*args)与字典参数(**kwargs)

二、装饰器初识

首先我们有一个func函数,如下:

def func():
    time.sleep(1)
    print("执行了func()函数")

如果我们需要测试函数的执行时间,我们是否可以简单粗暴的在函数内部加个时间计算的代码,如下:

import time

def func():
	# 标记开始执行时间
	start_time = time.time()
    
    # 函数原逻辑代码
    time.sleep(1)
    print("执行了func()函数")
    
    # 标记结束执行时间
    end_time = time.time()
    
    # 计算函数执行时间,并打印
    delta_time = end_time - start_time
    print("{}的执行时间:{}".format(f, delta_time))

一分钟不到,搞定测试函数执行时间,但是却怎么看着怎么别扭,函数内部增加了很多计算时间代码,有种掩盖原逻辑的赶脚,一点都不优雅;倘若有一百个函数需要测试执行时间,那就工作量可想而知,于是我们想办法,有没有不改变原函数源代码与调用方式,但是又可以计算出原函数,我们先写一个计算执行时间的函数,如下:

def calculate_time(f):
    """装饰器函数"""
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        delta_time = end_time - start_time
        print("{}的执行时间:{}".format(f, delta_time))
    # 将传入额函数地址返回到外部,即不调用则不执行
    return wrapper


def func():
    """需要被装饰的函数,测试此函数的执行时间"""
    time.sleep(1)
    print("执行了func()函数")


# (1)调用装饰器函数
# func 是一个标识符,此时func被覆盖为calculate_time()中的wrapper
print("【原来的func()函数】函数名:{},地址:{}".format(func.__name__, func))
func = calculate_time(func)
print("【现在的func()函数】函数名:{},地址:{}".format(func.__name__, func))
# (2)执行func()函数
# calculate_time()中的wrapper()函数,同时会执行原来的func()
print("---准备调用func()---")
func()

# =======控制台输出结果=======
【原来的func()函数】函数名:func,地址:<function func at 0x000002C3E38A98C8>
【现在的func()函数】函数名:wrapper,地址:<function calculate_time.<locals>.wrapper at 0x000002C3E38A9950>
---准备调用func()---
执行了func()函数
<function func at 0x000002C3E38A98C8>的执行时间:1.0002367496490479
# =======控制台输出结果=======

虽然最后func()函数发生改变,但是并未改变原函数源代码,而且调用方式也未改变,就相当于给原func()函数扩展了一个计算执行时间的功能,新func() = 原func() + 计算执行时间的功能,这也是聪明的前辈们总结出来——最原始的Python装饰器,后面随着Python的发展,有了一个调用装饰器的语法糖,语法如下:

@装饰器名称
def func_name()"""被装饰函数"""
	pass

于是,上述代码等价于:

import time


def calculate_time(f):
    """装饰器函数"""
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        delta_time = end_time - start_time
        print("{}的执行时间:{}".format(f, delta_time))
    # 将传入额函数地址返回到外部,即不调用则不执行
    return wrapper


@calculate_time
def func():
    """需要被装饰的函数,测试此函数的执行时间"""
    time.sleep(1)
    print("执行了func()函数")


func()

版权声明:本文为博主原创文章,如需转载,请给出:
原文链接:https://blog.csdn.net/qq_35844043/article/details/104457037

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Commas.KM

码路共同进步,感恩一路有您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值