Python 装饰器
Python 装饰器
装饰器是什么东西呢?想必大家也多少了解过了一点,它就是实现了我们在不修改原有函数的基础上,给函数或方法增加新的功能,其实装饰器本身也是一个函数,她接收一个函数作为参数并返回一个新的函数,这个新的函数通常包含原函数的调用,并包含一额外新增的功能。
那么在了解装饰器之前呢,你需要了解一个东西叫做闭包,只有了解了它你才能更加了解装饰器。那么可以看我之前写的关于闭包的文章。
链接:https://8888666.top/2024/08/05/python%E9%97%AD%E5%8C%85/
代码解释
使用类定义函数装饰器未带参数
1 |
|
代码解释: 上述代码就是简单实现了一个装饰器。
1.首先我定义一个函数,这个函数用来模拟我们打开我的网站的一个对话,整个函数就是打印了一串文字,retrun 了一串文字。
2.然后我定义了一个装饰器MyBlogDecorator,在装饰器中首先在__init__
方法中我们定义的function 此时传入的并不是一个变量,而是一个函数,这就是装饰器的灵魂所在。
3.那么我们还定义了魔法函数__call__
在运行类MyBlogDecorator,会自动调用我们的 __call__
方法,那么在__call__
方法中我们设置了可以传入参数设置,也就是假设你的open_blog 函数需要传变量,那么这里也是可以完美支持,只不过我们的案例中没写而已。
4.在里面我们也是首先打印了一串文字,然后此时调用了我们的self.function(*args, **kwargs)这里其实就是将open_blog() 函数进行了调用,然后程序会执行open_blog,然后输出”welcome to my blog”, 此时result_info 进行接收return 返回的值,然后打印“The blog is download, now you can see!”,最后程序输出return的值oh,is very nice blog。
完整的输出信息:
1 |
|
相信大家在此刻也就对装饰器了解更加彻底了!
使用类定义函数装饰器带参数
1 |
|
代码解释: 那么如果你看了上述的代码解释,我这里就不会在详细的讲解每一步了,这里我主要来讲不一样的地方。
1.首先我们这里发生变化的地方是我们的装饰器增加了参数,也就是name,我们通过MyBlogDecorator进行了传递name是 xiaoming 的参数,但是要注意的是此时我们接收的name就是在__init__
方法里,和上述不一样的是我们这里不能接收函数了。
2.我们需要写一个函数的装饰器进行接收,也就是在__call__
里面进行接收fucntion ,然后通过内部的函数 wrap 进行调用,此时我们需要注意在进入__call__
中我们首先执行的是return warp 让warp函数执行,然后我们里面的和我们上述讲的程序执行就是一样的了。
代码输出结果:
1 |
|
给类添加装饰器
1 |
|
代码解释:上述代码定义了一个类Open_blog, 然后类里面打印了一串文字,我们定义了一个装饰器cls_MyBlogDecorator,此时装饰器实现了将Open_blog传入到了cls_MyBlogDecorator中, 也就是cls,然后打印了一串文字,return了 cls 也就调用了Open_blog 这个类 输出了 welcome to my blog
程序输出结果:
1 |
|
那么,如果我重复调用Open_blog() 这个类会发生什么呢?大部分同学应该会说,那肯定输出上面的两串文字 两次,那么现实真的是吗?
1 |
|
程序输出:
1 |
|
哈哈,大家发现了没有,此时我们调用两次也没有执行输出两次,是因为我们的装饰器已经装饰完到内存了,你虽然调用了两次,但是每次调用的还是那个装饰器装饰到内存的那个,所以会只是输出一次,那么怎么让他输出两次呢? 可以这样来
1 |
|
代码解释: 此时我们进行了改进在之前的函数中新增了inner函数,此时逻辑变为当我们每次调用的Open_blog 这个类的时候实际我们在调用inner这个函数,函数里面呢将类进行了实例化,此时我们return 底部的也变为了inner,也就是每次调用都会执行inner()这个函数。
程序输出:
1 |
|
这样你就会发现我们每调用一次都会调用一次inner里面的!
总结
python 中的装饰器是一种了非常灵活的方式来增强函数的功能,而不需要修改函数本身的代码。它们是函数式编程在 Python 中的一种优雅体现,能够极大地提高代码的可读性和可维护性。在众多的设计模式中也用的非常多,例如我们的日志记录、性能测试、事务处理、权限校验等,以及我们在使用Pytest 框架的时候我们会用到很多框架提供给我们的装饰器,非常强大且使用方便!