侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

绿泡泡:___zze,添加备注来意

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

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

zze
zze
2019-03-29 / 0 评论 / 0 点赞 / 329 阅读 / 3237 字

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

原始版本

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 内部给我们提供了语法糖支持。在需要被装饰的函数名上部使用 @装饰器函数名称 即可。

0

评论区