Code前端首页关于Code前端联系我们

Python基础入门笔记:装饰器

terry 2年前 (2023-09-25) 阅读数 49 #后端开发

装饰器

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。

使用函数编程是不是很方便?然而,我们每次调用它时都需要将原始函数作为参数传递。有一个更好的方法吗?是的,我将在本文中介绍装饰器,因为装饰器的编写方式实际上与闭包方法类似,但没有自由变量。那么这里就在上面的代码中写一个装饰器的方法来进行对比。脚本编程和函数式编程有什么区别?

  1. 输出:
    2018-01-09
    昵称:两点水  部门:研发部 上班打卡成功
    复制代码

    通过代码,可以知道装饰器函数一般会做这三件事:

    1. 接受一个函数作为参数
    2. 嵌套一个包装函数,包装函数会收到与原函数参数并执行原函数的同时还执行附加功能
    3. 返回嵌套函数

    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前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门