装饰器
自学python时,觉得装饰器是个很难理解的概念,后来也一直没机会使用它。最近看到公众号早起Python的《人人都能看懂的Python装饰器入门教程!》,很受启发,撰文记之。
1. 定义与原则
先来看装饰器的定义:
一种增加函数功能的简单方法,可以快速地给不同的函数或类插入相同的功能。
它有两个原则
1)不能修改被装饰函数的原代码
2)不能修改被装饰函数的调用方式
2. 案例
定义并不是很好理解,我们先来看一个案例。
比如我们有一个猫的方法和一个狗的方法如下:
def cat():
print('This is a cat.')
def dog():
print('This is a dog.')
它们的调用方法和调用结果如下:
现在我们想要猫的方法在打印“This is a cat.”前先打印一个“This is an animal.”,要狗的方法在打印“This is a dog.”前也先打印一个“This is an animal.”。我们可以用装饰器的方式来实现,即写一个装饰器函数如下:
def animal(func):
def print_():
print('This is an animal.')
func()
return print_
从两个函数的原代码、调用和调用结果可以看到,这是符合装饰器的原则的。
当然,它其实还不是完整的装饰器,请容我稍后再议。
3. 原理
装饰器的基本原理其实是以函数为参数的调用与返回,如下图所示:
就是调用animal函数是以cat和dog函数名作为参数,返回结果是print_函数。
3.1. functools
但是,上述经过装饰器装饰后cat或dog方法的调用发生了一个变化。我们原来想要调用cat方法或dog方法,但结果却成了调用print_方法。
为此python提供了一个库叫functools,掉用它里面的wraps来装饰print_函数,就能解决问题。只需要将装饰器做出下改动即可:
import functools
def animal(func):
@functools.wraps(func)
def print_():
print('This is an animal.')
func()
return print_
至于functools.wraps是如何达到这个功能的,网上也有很多资料,我们这里就只研究如何让电灯发光,不讨论如何发电了。
3.2. 传参
但还有一个问题是我们所关心的,那就是如何传参。
当我们的cat方法和dog方法带有参数时,装饰器是如何传参的?比如我们的cat方法如下:
def cat(name):
print('This is ' + name + '.')
这就要求我们的print_方法同样进行传参,需要进一步改写如下:
import functools
def animal(func):
@functools.wraps(func)
def print_(*args, **kwargs):
print('This is an animal.')
func(*args, **kwargs)
return print_
参考文献:
-
https://mp.weixin.qq.com/s/gGcBazI8Qr31RhiB9EhOVA -
https://www.cnblogs.com/wendyw/p/9724231.html
- 点赞
- 收藏
- 关注作者
评论(0)