Python中的装饰器及其应用场景

2024-09-07 08:20
文章标签 python 应用 场景 装饰

本文主要是介绍Python中的装饰器及其应用场景,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python中的装饰器(Decorators)是一个非常强大且优雅的特性,它允许你在不修改原有函数或类定义的情况下,给函数或类增加新的功能。装饰器本质上是一个函数,它接收一个函数(或类)作为参数,并返回一个新的函数(或类),这个新函数(或类)会包含原函数(或类)的所有功能,并在其基础上增加额外的功能。装饰器的这种特性使得代码的重用性、可读性和可维护性都得到了极大的提升。

一、装饰器的基本概念

在Python中,函数是一等公民,这意味着函数可以像其他数据类型一样被赋值给变量、作为参数传递给其他函数、以及作为其他函数的返回值。装饰器正是基于这一特性实现的。装饰器通常遵循以下原则:

  1. 不修改被装饰函数的源代码:这是保持代码原有逻辑不变的重要原则。
  2. 不修改被装饰函数的调用方式:即装饰后的函数(或类)在调用时,其方式应与原函数(或类)保持一致。

二、装饰器的实现方式

装饰器的实现通常分为两步:

  1. 定义一个装饰器函数:这个函数接收一个函数作为参数,并返回一个新的函数。新函数内部会调用原函数,并可以在调用前后添加额外的功能。
  2. 使用@语法糖将装饰器应用于目标函数:这是Python提供的一种语法糖,用于简化装饰器的应用过程。
示例:简单的装饰器
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.

在上面的例子中,my_decorator是一个装饰器函数,它接收了一个函数say_hello作为参数,并返回了一个新的函数wrapperwrapper函数在调用say_hello函数之前和之后分别打印了一些信息。通过使用@my_decorator语法糖,我们将my_decorator装饰器应用到了say_hello函数上,使得在调用say_hello时,实际上调用的是经过装饰的wrapper函数。

三、装饰器的应用场景

装饰器的应用场景非常广泛,几乎可以在任何需要在不修改原有代码逻辑的情况下增加额外功能的场景中使用。以下是一些典型的应用场景:

1. 日志记录

在函数执行前后记录日志是一种常见的需求。使用装饰器可以很容易地实现这一点,而无需修改每个函数的内部逻辑。

def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Function {func.__name__} is called with arguments {args} and keyword arguments {kwargs}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} returned {result}")
return result
return wrapper
@log_decorator
def add(x, y):
return x + y
print(add(3, 4))
# 输出:
# Function add is called with arguments (3, 4) and keyword arguments {}
# Function add returned 7
2. 性能监控

在性能敏感的应用中,监控函数的执行时间是一个重要的需求。装饰器可以很方便地用于此目的。

import time
def timeit_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.6f} seconds to execute.")
return result
return wrapper
@timeit_decorator
def long_running_task():
# 假设这里有一些耗时的操作
time.sleep(1)
long_running_task()
# 输出:
# Function long_running_task took approximately 1.000xxx seconds to execute.
3. 权限校验

在Web应用中,对用户的操作进行权限校验是一个常见的需求。装饰器可以用于在用户执行某个操作之前检查其权限。

def auth_decorator(func):
def wrapper(*args, **kwargs):
# 假设这里有一个验证用户权限的函数
if not verify_user_permission():
return "Access denied"
return func(*args, **kwargs)
return wrapper
# 假设的验证用户权限函数
def verify_user_permission():
# 这里应该有实际的权限验证逻辑
return True # 假设用户有权限
@auth_decorator
def sensitive_operation():
return "Sensitive data"
print(sensitive_operation())
# 输出:Sensitive data(如果用户有权限)
# 或者 Access denied(如果用户没有权限)
4. 缓存

对于一些计算量大或调用频率高的函数,使用缓存来存储其结果可以显著提高性能。装饰器可以用于实现函数的缓存机制。

def cache_decorator(func):
cache = {}
def wrapper(*args, **kwargs):
key = str(args) + str(kwargs)
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
return wrapper
@cache_decorator
def heavy_computation(x):
# 假设这里有一些复杂的计算
return x * x # 简化为平方运算
print(heavy_computation(5)) # 计算结果并缓存
print(heavy_computation(5)) # 直接从缓存中获取结果
# 输出两次相同的平方结果,但第二次调用不会进行实际的计算
5. 链式装饰器

Python的装饰器可以链式使用,即一个函数可以被多个装饰器装饰。这使得你可以在不同的层面为函数添加不同的功能,而无需担心它们之间的相互影响。

@decorator1
@decorator2
def func():
pass
# 等价于
func = decorator1(decorator2(func))

四、总结

Python中的装饰器是一个强大且灵活的工具,它允许你在不修改原有函数或类定义的情况下,为它们增加新的功能。通过合理地使用装饰器,你可以提高代码的重用性、可读性和可维护性。在实际开发中,装饰器的应用场景非常广泛,包括但不限于日志记录、性能监控、权限校验、缓存等。掌握装饰器的使用方法和原理,对于提高Python编程技能具有重要意义。

这篇关于Python中的装饰器及其应用场景的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1144559

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss