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

8 篇文章 0 订阅
6 篇文章 0 订阅

前导

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

还不了解的可以翻一下前面的篇章【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__)

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值