python中神奇的装饰器

需求:实现一个可以统计代码的运行时间-CSDN博客

装饰器就是我们常见的在类或函数上的@装饰器,比如unittest里@ddt,它可是一种好用的工具。如果你同事写了一坨代码,你想给这一坨代码扩展新的功能,这个时候就用到了装饰器,它的神奇在于,它既不改变原功能函数的内部代码,还不改变调用方法的情况下,就给你同事的这坨代码扩展了新的功能。该说不说,设计装饰器的大佬真是给我们带来了极大的方便。

装饰器原理:

@装饰器  等同于调用装饰器,就是把被装饰的函数,当成参数传入装饰器中,保存在封闭作用域中。

书接上回,上篇就是用装饰器实现了统计代码运行时间的功能, 上篇的函数装饰器,都是用闭包的形式;什么又是闭包呢?

闭包:简单的说就是 一个函数在一个封闭作用域内

形式:

一个函数嵌套一个函数;

外层函数return返回内层函数;

这样内层函数就保证在外层函数这个封闭作用域内了

在内层函数里:

扩展的代码1

被装饰的函数

扩展的代码2

这就给被装饰的函数扩展新功能啦。

def decorator(func):
    def wrapper():
        print("扩展的代码1")
        func()
        print("扩展的代码2")

    return wrapper


@decorator  # work = decorator(work)
def work():
    print("----------写代码-----------")

work()

这样一个基本的装饰器就完成啦。

这个时候,我们装饰的函数有参数,要怎么做呢?

def decorator(func):
    def wrapper(*args, **kwargs):
        print("-----------开机,打开软件--------------")
        res = func(*args, **kwargs)
        print("------------关机,底薪到手--------------")
        return res

    return wrapper


@decorator  # work = decorator(work)
def work(a, b):
    print("----------写代码-----------")
    return a + b


work(10, 30)

再复杂一点,我们装饰器本身带有参数呢? 

@decorator(5)  =====》等同于 被装饰的函数 = decorator(5)(被装饰的函数)

def decorator(n):
    """最外层的参数n,接收装饰器传进来的值"""

    def wrapper(func):
        """第二层参数func,接收被装饰的函数"""

        def wrapper1(*args, **kwargs):
            """第三次参数,接收被装饰的函数调用时传进来的参数"""
            print(n)
            print("装饰器扩展的功能代码1")
            res = func(*args, **kwargs)
            print("装饰器扩展的功能代码2")
            return res

        return wrapper1

    return wrapper


@decorator(5)  # work = decorator(5)(work)
def work():
    print("人生苦短,我学python")


work()

 至此,通过函数实现装饰器,就这些了。(提一句,装饰器有个副作用,问题也不大,在这儿就不介绍了。)

你就想啦,通过函数能实现装饰器,那能不能通过类实现装饰器呢?你是会举一反三的,当然可以啦。这个时候,你又学了一个魔术方法__call__,这个时候你就能通过类实现装饰器啦。

这个魔术方法有什么作用呢?类创建出来对象能不能调用,就取决于这个类中有没有魔术方法__call__。

import time


class CountTime:
    def __init__(self, func):
        # func:是被装饰的函数,传入进来之后保存为func属性
        self.func = func

    def __call__(self, *args, **kwargs):
        st = time.time()
        # 调用原功能函数
        res = self.func(*args, **kwargs)
        et = time.time()
        print("函数执行的时间为:", et - st)
        return res


@CountTime  # ===> work = CountTime(work)  实例化对象
def work():
    time.sleep(2)


work()

装饰器好神奇,怎么用好这个工具,还得看个人;用函数或者类实现装饰器,我这里都是装饰的函数,一样的,也可以去装饰器类,试着去写一下吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值