【Python函数式编程】——装饰器

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值 也是一个函数对象。它经常用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。

Python函数式编程——装饰器

在这里插入图片描述

1.什么是装饰器

先看一段代码:

# -*- coding: utf-8 -*-
# @File  : 什么是装饰器.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 19:38


def fun():
    print('洗脸')


fun()  # 调用fun函数
# 洗脸


# 想给fun函数增加 起床 和 吃早点 这两个功能
def test1(func):
    def test2():
        print('起床')
        func()
        print('吃早点')
    return test2


test1(fun)()
# 起床
# 洗脸
# 吃早点
  由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。也可以将函数赋值变量,做参传入另一个函数。
  装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值 也是一个函数对象。

  它经常用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。

2.装饰器的作用

装饰器的作用:为已经存在的对象添加额外的功能

看代码代码:

# -*- coding: utf-8 -*-
# @File  : 装饰器.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 19:46


def test1(func):
    def test2():
        print('起床')
        func()
        print('吃早点')
    return test2


@test1  # 装饰器
def fun():
    print('洗脸')


fun()
# 起床
# 洗脸
# 吃早点
  我们没有直接将 fun函数作为参数传入 test1中,只是将 test1函数以@方式装饰在 fun函数上。

  也就是说,被装饰的函数,函数名作为参数,传入到装饰器函数上,不影响fun函数的功能,再此基础上可以根据业务或者功能增加条件或者信息。

(注意:@在装饰器这里是作为Python语法里面的语法糖写法,用来做修饰。)

  但是我们这里就存在一个问题,这里引入魔术方法 __name__ ,这是属于 python 中的内置类属性,它天生就存在于一个 python 程序中,代表对应程序名称,一般一段程序作为主线运行程序时其内置名称就是 __main__ ,当自己作为模块被调用时就是自己的名字。
print(fun.__name__)
# test2
  这并不是我们想要的!输出应该是 fun,这里的函数被 test2替代了。它重写了我们函数的名字和注释文档,那怎么阻止变化呢,Python提供 functools模块里面的 wraps函数解决了问题。

代码实现:

# @Time  : 2022/8/21 20:04

from functools import wraps


def test1(func):
    @wraps(func)  # 使用fun来包装test2
    def test2():
        print('起床')
        func()
        print('吃早点')
    return test2


@test1  # 装饰器
def fun():
    print('洗脸')


fun()
print(fun.__name__)  # fun

在这里插入图片描述

我们在装饰器函数内,作用 funtest2函数上也增加了一个装饰器 wraps还是带参数的,这个装饰器的功能就是不改变使用装饰器原有函数的结构。

3.装饰器记录日志功能

work()函数增加记录日志功能

# -*- coding: utf-8 -*-
# @File  : 装饰器实现记录日志功能.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 20:09

import time
from functools import wraps


def log(fun):
    @wraps(fun)
    def write_log():
        print("[info]--时间是:%s" % time.strftime("%Y-%m-%d %H:%M:%S"))
        fun()
    return write_log


@log
def work():
    print("我在学习Python")


work()

在这里插入图片描述

4.带参装饰器

  我们也看到装饰器 wraps也是带参数的,那我们是不是也可以定义带参数的装饰器呢,我们可以使用一个函数来包裹装饰器,调入这个参数。
# -*- coding: utf-8 -*-
# @File  : 带参数的装饰器.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 21:01

import time
from functools import wraps


def logs(func):
    @wraps(func)
    def write_log(*args, **kwargs):
        print('[info]--时间:%s' % time.strftime('%Y-%m-%d %H:%M:%S'))
        func(*args, **kwargs)
    return write_log


@logs
def work():
    print('我在工作')


@logs
def work2(name1, name2):
    print('%s和%s在工作' % (name1, name2))


work2('张三', '李四')
# [info]--时间:2022-06-24 18:04:04
# 张三和李四在工作

在这里插入图片描述


5.函数做装饰器

把日志写入文件

# -*- coding: utf-8 -*-
# @File  : 把日志写入文件.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 21:14

import time
from functools import wraps


def logger(log_file):
    def logs(fun):
        @wraps(fun)
        def write_log(*args, **kwargs):
            log = "[info]--时间是:%s" % time.strftime('%Y-%m-%d %H:%M:%S')
            print(log)
            with open(log_file, 'a+') as f:
                f.write(log+'\n')
            fun(*args, **kwargs)
        return write_log
    return logs


@logger('work.log')  # 使用装饰器来给 work函数增加记录日志的功能
def work(name1, name2):  # 1.当前 work可能有多个参数 2.自定义日志文件的名字和位置,记录日志级别
    print(f"{name1}和{name2}正在工作")


work('张三', '李四')

终端输出:
在这里插入图片描述
work.log文件记录日志
在这里插入图片描述

  这里我们将带参数的带入进去根据代码流程执行生成了文件并将日志信息打印进去现在我们有了能用于正式环境的 logger装饰器,但当我们的应用的某些部分还比较脆弱时,异常也许是需要更紧急关注的事情。

6.类做装饰器

# -*- coding: utf-8 -*-
# @File  : 把日志写入文件.py
# @author: Flyme awei 
# @email : Flymeawei@163.com
# @Time  : 2022/8/21 21:14

import time
from functools import wraps


class Log(object):
    def __init__(self, log_file, level="INFO"):
        self.log_file = log_file
        self.level = level

    def __call__(self, fun):  # 定义装饰器,需要有一个接受函数
        @wraps(fun)
        def write_log(*args, **kwargs):
            log = "[%s]--时间是:%s" % (self.level, time.strftime('%Y-%m-%d %H:%M:%S'))
            print(log)
            with open(self.log_file, 'a+') as f:
                f.write(log+'\n')
            fun(*args, **kwargs)
        return write_log


@Log('work3.png')
def learn(name):
    print(f"{name}在学习Python")


@Log('work2.log')  # 使用装饰器来给 work函数增加记录日志的功能
def work(name1, name2):  # 1.当前 work可能有多个参数 2.自定义日志文件的名字和位置,记录日志级别
    print(f"{name1}和{name2}正在工作")


learn("Flyme awei")
work('张三', '李四')

在这里插入图片描述

  类实现装饰器有一个优势,在于比嵌套函数的方式更加整洁,而且包裹一个函数还是使用跟以前一样的语法。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
7天前
|
缓存 测试技术 Python
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
157 99
|
7天前
|
存储 缓存 测试技术
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
141 98
|
11天前
|
缓存 Python
Python中的装饰器:优雅地增强函数功能
Python中的装饰器:优雅地增强函数功能
|
21天前
|
存储 缓存 测试技术
理解Python装饰器:简化代码的强大工具
理解Python装饰器:简化代码的强大工具
|
1月前
|
程序员 测试技术 开发者
Python装饰器:简化代码的强大工具
Python装饰器:简化代码的强大工具
156 92
|
3月前
|
Python
掌握Python装饰器:轻松统计函数执行时间
掌握Python装饰器:轻松统计函数执行时间
270 76
|
26天前
|
设计模式 缓存 运维
Python装饰器实战场景解析:从原理到应用的10个经典案例
Python装饰器是函数式编程的精华,通过10个实战场景,从日志记录、权限验证到插件系统,全面解析其应用。掌握装饰器,让代码更优雅、灵活,提升开发效率。
87 0
|
4月前
|
人工智能 API Python
掌握 Python 文件处理、并行处理和装饰器
本文介绍了 Python 在文件处理、并行处理以及高级功能(如装饰器、Lambda 函数和推导式)的应用。第一部分讲解了文件的基本操作、读写方法及处理大型文件的技巧,并演示了使用 Pandas 处理结构化数据的方式。第二部分探讨了多线程与多进程的并行处理,以及 `concurrent.futures` 模块的简化用法,适合不同类型的任务需求。第三部分则深入装饰器的实现与应用,包括简单装饰器、带参数的装饰器及 `functools.wraps` 的使用,同时简要介绍了 Lambda 函数和推导式的语法与场景。内容实用且全面,帮助读者掌握 Python 高效编程的核心技能。
|
9月前
|
测试技术 数据安全/隐私保护 开发者
探索Python中的装饰器:从基础到高级应用
装饰器在Python中是一个强大且令人兴奋的功能,它允许开发者在不修改原有函数代码的前提下增加额外的功能。本文将通过具体代码示例,带领读者从装饰器的基础概念入手,逐步深入到高级用法,如带参数的装饰器和装饰器嵌套等。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
109 6

推荐镜像

更多