本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名原文链接~~~

Python基础(14)之装饰器入门

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:


从一个小例子来了解装饰器,现要统计一个函数执行耗时:

原始版本

import time

# time模块有提供时间相关函数
def do_something():
    print("do_something")
    time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时

start = time.time()
do_something()
print(time.time() - start)
#result:
# do_something
# 0.5000283718109131

问题:上述代码可以完成这个功能,但之后会发现,如果我们要统计其它函数,就必须在每个函数前后加入相应代码。

装饰器版本 1(无参数)

import time

def execute_time(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)

    return inner

# time模块有提供时间相关函数
def do_something():
    print("do_something")
    time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时

do_something = execute_time(do_something)
do_something()
#result:
# do_something
# 0.5000283718109131

从上述代码可以看到,使用了另一个函数 execute_time 给我们要统计耗时的函数进行了包装。此时,这个 execute_time 函数就叫做装饰器函数,而我们要统计的那个函数也就是 do_something 函数就是被装饰的函数。

问题:函数执行的时候实际上是调用的 execute_time 函数中的 inner 函数,这种方法虽然解决了原始版本的问题,但是当我们要统计的函数拥有返回值的时候,这时候我们获取不到返回值。

装饰器版本 2(有固定参数)

import time

def execute_time(func):
    def inner(do):
        start = time.time()
        result = func(do)
        print(time.time() - start)
        return result
    return inner

# time模块有提供时间相关函数
def do_something(do):
    print("do_something", do)
    time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    return 'do_something over'

do_something = execute_time(do_something)
print(do_something('say hello'))
# result:
# do_something say hello
# 0.5000283718109131
# do_something over

为了解决装饰器版本 1 的问题,我在 inner 函数里面加了个返回值。

问题:当被装饰函数的参数个数与 inner 参数个数不同时,这个装饰器就不适用了。

装饰器版本 3(动态参数)

import time

def execute_time(func):
    def inner(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(time.time() - start)
        return result

    return inner

# time模块有提供时间相关函数
def do_something(do1,do2):
    print("do_something", do1,do2)
    time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    return 'do_something over'

do_something = execute_time(do_something)
print(do_something('say hello1','say hello2'))
# result:
# do_something say hello1 say hello2
# 0.5000283718109131
# do_something over

在之前有个动态参数的知识点,正好可以解决上一步的问题。

终极版本(语法糖 @)

import time

def execute_time(func):
    def inner(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(time.time() - start)
        return result

    return inner

@execute_time
def do_something(do1,do2):
    print("do_something", do1,do2)
    time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    return 'do_something over'

# do_something = execute_time(do_something)
print(do_something('say hello1','say hello2'))
# result:
# do_something say hello1 say hello2
# 0.5000283718109131
# do_something over

对于装饰器,python 内部给我们提供了语法糖支持。在需要被装饰的函数名上部使用 @装饰器函数名称 即可。


如果这篇文章对您有帮助,可点击下方链接分享给你的朋友们😋,如果遇到问题欢迎评论、留言~~~😇

评论

公众号:zze_coding

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×