Python基础入门笔记:装饰器
装饰器
7.1什么是装饰器
通过请求一步步了解Python装饰器。首先有一个函数,输出员工登录信息:
def punch():
print('昵称:两点水 部门:做鸭事业部 上班打卡成功')
punch()
复制代码
输出:
昵称:两点水 部门:做鸭事业部 上班打卡成功
复制代码
然后,产品反馈,不对,为什么上班没有具体的登录日期?只需添加具体的入住日期即可。这应该很简单。几分钟内就解决了。好吧,我们就添加打印日期的代码吧,如下:
import time
def punch():
print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
print('昵称:小明 部门:研发部 上班打卡成功')
punch()
复制代码
输出:
2018-01-09
昵称:小明 部门:研发部 上班打卡成功
复制代码
这样改也可以,但是改变了函数的功能结构。定义此函数后,它将打印已成功登录的员工的详细信息和提示。现在添加代码来打印日期可能会导致许多代码重复问题。比如还有一个地方只需要打印员工信息并登录成功,但是不需要日期,所以要重写函数吗?另外,这种打印当前日期的函数方法经常被使用,并且可以作为每个模块的方法的公共函数来调用。当然,所有这些都被视为一个整体项目。
这种情况下,我们可以使用函数式编程来改变这部分代码。因为我们通过前面的学习知道Python函数有两个特点。函数也是一个对象,并且函数可以嵌套在函数中。然后将代码更改为如下所示:
import time
def punch():
print('昵称:小明 部门:研发部 上班打卡成功')
def add_time(func):
print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
func()
add_time(punch)
复制代码
输出:
2018-01-09
昵称:小明 部门:研发部 上班打卡成功
复制代码
This is This is not a discovery.这样,punch
方法就不会改变,任何需要打印当前日期的函数都可以简单地将函数传递给add_time。
使用函数编程是不是很方便?然而,我们每次调用它时都需要将原始函数作为参数传递。有一个更好的方法吗?是的,我将在本文中介绍装饰器,因为装饰器的编写方式实际上与闭包方法类似,但没有自由变量。那么这里就在上面的代码中写一个装饰器的方法来进行对比。脚本编程和函数式编程有什么区别?
- 输出:
2018-01-09 昵称:两点水 部门:研发部 上班打卡成功 复制代码
通过代码,可以知道装饰器函数一般会做这三件事:
- 接受一个函数作为参数
- 嵌套一个包装函数,包装函数会收到与原函数参数并执行原函数的同时还执行附加功能
- 返回嵌套函数
7.2 语法糖
从上面的代码中我们可以看到,Python 在引入装饰器(Decorator)时,并没有介绍。没有新的语法函数是基于函数语法函数的。这也说明了装饰器并不是Python独有的,而是每个语言共有的编程思想。只有Python设计了
@
语法糖,使得定义装饰器、调用原函数的装饰器、并将结果赋值给原函数的对象名的过程变得更加简单。方便易用,所以可以说Python装饰器的核心是语法糖。那么如何利用它的语法甜蜜呢?这很简单。按照上面的写法编写装饰器函数时,将
@
和装饰器函数的名称直接添加到原函数中。像这样:import time def decorator(func): def punch(): print(time.strftime('%Y-%m-%d', time.localtime(time.time()))) func() return punch @decorator def punch(): print('昵称:小明 部门:研发部 上班打卡成功') punch() 复制代码
输出:
2018-01-09 昵称:小明 部门:研发部 上班打卡成功 复制代码
那么这对于我们的调用来说是非常方便的。比如例子中,使用装饰器后,我们可以直接在原来的函数中添加装饰器的语法糖。就是这样,这个函数没有改变,调用站点也不需要改变。
但是,这里一直有一个问题,就是登录数据的输出是固定的,所以我们需要通过参数来传递。如何写一个装饰器?装饰器中的函数可以使用可变参数
*args
,但仅使用*args
无法完全包含所有参数。例如,不能使用关键字参数。我们还需要添加**kwargs
以实现关键字参数兼容性。因此,装饰器的最终形式可以写成如下:
import time def decorator(func): def punch(*args, **kwargs): print(time.strftime('%Y-%m-%d', time.localtime(time.time()))) func(*args, **kwargs) return punch @decorator def punch(name, department): print('昵称:{0} 部门:{1} 上班打卡成功'.format(name, department)) @decorator def print_args(reason, **kwargs): print(reason) print(kwargs) punch('小明', '研发部') print_args('小明', sex='男', age=99) 复制代码
输出结果:
2018-01-09 昵称:小明 部门:研发部 上班打卡成功 2018-01-09 小明 {'sex': '男', 'age': 99}
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。