【Python】函数「三」——装饰器

导读:本篇文章讲解 【Python】函数「三」——装饰器,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前导

  • 在学习了闭包后,我们知道在函数里面嵌套一个子函数,子函数可以调用父函数的变量
  • 在学习了回调函数后,我们知道函数名可以作为参数传递

还不了解的可以翻一下前面的篇章【Python】函数「二」——闭包和回调函数学习一下,在了解闭包和回调函数后,装饰器就很好理解了


什么是装饰器

简单来说,装饰器就是在不改变原函数定义代码的情况下,根据需求对函数进行修改(或者说装饰)。这里我们先看一个简单的例子

import time

# sleep 0.5秒,然后输出hello world
def hello():
    time.sleep(0.5)
    print("hello world")

# 定义一个装饰器,接收函数func为参数
# 在函数开始前记录下当前时间,在函数结束后输出函数总用时
def print_time(func):
    def wrapper():
        start = time.time()
        func()
        print("total time:", time.time()-start)
    return wrapper

# 为hello函数装饰
hello_ = print_time(hello)
hello_()


装饰带参数的函数

import time

# sleep s秒,然后输出hello world
def hello(s):
    time.sleep(s)
    print("hello world")

def print_time(func):
    # print_time(func)返回函数对象
    def wrapper(*args, **kwargs):
        start = time.time()
        # 参数的嵌套传递,print_time(func)(*args, **kwargs)返回值
        func(*args, **kwargs) # 这里如果看不懂,可以参考我之前的博客——函数的参数传递
        print("total time:", time.time()-start)
    return wrapper

# 为hello函数装饰
hello_ = print_time(hello)
hello_(1) # 相当于print_time(hello)(1)


使用语法糖,更便捷地装饰函数

这是一开始的例子,咱们利用语法糖”@+装饰器函数名“可以直接对原函数进行装饰

import time

# 定义一个装饰器,接收函数func为参数
def print_time(func):
    def wrapper():
        start = time.time()
        func()
        print("total time:", time.time()-start)
    return wrapper


@print_time # 为hello函数装饰
def hello():
    time.sleep(0.5)
    print("hello world")

hello()


带参数的装饰器

有时候我们需要为某几类函数写装饰器,除了一小部分配置值外其余完全一致,那么我们就可以把配置信息独立为参数,在普通装饰器外面再嵌套一层即可。下面这个例子还是一开始的例子,这次我们希望能够在装饰器上指定函数func的运行次数:

import time

# 运行func函数num次
def run_again(num):
    def print_time(func):
        def wrapper():
            start = time.time()
            for _ in range(num):
            	func()
            print("total time:", time.time()-start)
        return wrapper
    return print_time

@run_again(3)
def hello():
    time.sleep(0.5)
    print("hello world")

hello() # 相当于run_again(3)(hello)()


保留被装饰函数的注释

在装饰函数后,我们会发现原函数的注释被替换掉了

在这里插入图片描述

那么,如何保留注释呢?也很简单,请看代码:

import time
from functools import wraps # 引入functools中的wraps

def print_time(func):
    @wraps(func) # 使用wraps装饰器保留注释
    def wrapper():
        """
        这里是wrapper
        """
        start = time.time()
        func()
        print("total time:", time.time()-start)
    return wrapper

@print_time
def hello():
    """
    hello world
    """
    time.sleep(0.5)
    print("hello world")

print(hello.__doc__)

如果我的分享能帮助到你,那我的分享就多了一份意义;如果有错误的地方劳烦指出,期待共同进步!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/97103.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!