1. 关于装饰器这一概念的基本知识, 其中的第一小节内容探讨了这样一个问题, 即究竟什么是装饰器?装饰器属于一种设计模式, 这种设计模式允许在不修改原始函数代码的前提情况下, 往函数内部添加全新的功能内容, 它属于语法糖的一种范畴, 是基于闭包机制以及高阶函数来实现相关效果的。1.第2点, 装饰器究竟是什么东西。从本质上来讲, 这个可调用对象就是装饰器。它的主要功能是接收一个函数当作参数。然后它会返回一个新的函数给你。def decorator(func):def wrapper(*args, **kwargs):# 添加新功能result func(*args, **kwargs)# 添加新功能return resultreturn wrapper2. 关于装饰器的基础知识这一部分, 我们来到了第二小节, 也就是编号为2.1的函数基础知识回顾环节。# 1. 函数是一等公民可以赋值给变量def greet(name):return fHello, {name}!say_hello greet # 函数赋值给变量print(say_hello(Alice)) # Hello, Alice!# 2. 函数可以作为参数传递def apply_function(func, value):return func(value)def square(x):return x * xprint(apply_function(square, 5)) # 25# 3. 函数可以嵌套定义def outer():def inner():return Inner functionreturn inner()# 4. 闭包函数可以记住它被创建时的环境def make_multiplier(n):def multiplier(x):return x * nreturn multipliertimes_3 make_multiplier(3)print(times_3(4)) # 123. 针对基础级别的装饰器这一块内容, 我们展开详细讲解。# 最简单的装饰器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 wrappermy_decoratordef say_hello():print(Hello!)say_hello()# 输出# Something is happening before the function is called.# Hello!# Something is happening after the function is called.3.这是关于第二个部分的内容, 主要是讲解那些带有参数的函数装饰器。def timer_decorator(func):import timedef wrapper(*args, **kwargs):start_time time.time()result func(*args, **kwargs)end_time time.time()print(f{func.__name__} executed in {end_time - start_time:.4f} seconds)return resultreturn wrappertimer_decoratordef slow_function(seconds):time.sleep(seconds)return fSlept for {seconds} secondsprint(slow_function(2))# 输出# slow_function executed in 2.0023 seconds# Slept for 2 seconds3.3 带参数的装饰器def repeat(num_times):装饰器工厂函数返回一个装饰器def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):result func(*args, **kwargs)return resultreturn wrapperreturn decorator_repeatrepeat(num_times3)def greet(name):print(fHello, {name}!)greet(Alice)# 输出# Hello, Alice!# Hello, Alice!# Hello, Alice!3.4 保留函数元信息from functools import wrapsdef preserve_metadata_decorator(func):wraps(func) # 使用wraps保留原函数的元信息def wrapper(*args, **kwargs):包装函数的文档print(fCalling {func.__name__})return func(*args, **kwargs)return wrapperpreserve_metadata_decoratordef calculate_sum(a, b):计算两个数的和return a bprint(calculate_sum.__name__) # calculate_sum如果不使用wraps会是wrapperprint(calculate_sum.__doc__) # 计算两个数的和print(calculate_sum(3, 4)) # 74. 所谓类装饰器这一章节的内容, 其主题是讨论4.1部分, 也就是要把一个类当作装饰器来使用的情景。class TimerDecorator:def __init__(self, func):self.func funcdef __call__(self, *args, **kwargs):import timestart_time time.time()result self.func(*args, **kwargs)end_time time.time()print(fExecution time: {end_time - start_time:.4f} seconds)return resultTimerDecoratordef long_running_operation():time.sleep(1)return Operation completedprint(long_running_operation())4.2 带参数的类装饰器class RetryDecorator:def __init__(self, max_retries3):self.max_retries max_retriesdef __call__(self, func):def wrapper(*args, **kwargs):for attempt in range(self.max_retries):try:return func(*args, **kwargs)except Exception as e:if attempt self.max_retries - 1:raiseprint(fAttempt {attempt 1} failed: {e}. Retrying...)return Nonereturn wrapperRetryDecorator(max_retries3)def unstable_function():import randomif random.random() 0.7:raise ValueError(Random failure!)return Success!print(unstable_function())5. 关于另外的一些装饰器的应用, 在章节的第五点第一个小标题部分, 提到了存在多个装饰器这样的状况。def decorator1(func):wraps(func)def wrapper(*args, **kwargs):print(Decorator 1: Before)result func(*args, **kwargs)print(Decorator 1: After)return resultreturn wrapperdef decorator2(func):wraps(func)def wrapper(*args, **kwargs):print(Decorator 2: Before)result func(*args, **kwargs)print(Decorator 2: After)return resultreturn wrapperdecorator1decorator2def say_hello():print(Hello!)say_hello()# 输出# Decorator 1: Before# Decorator 2: Before# Hello!# Decorator 2: After# Decorator 1: After# 注意装饰器从下往上执行5.第2部分要讲的是装饰器以及与类方法相关的这些内容。def method_decorator(func):wraps(func)def wrapper(self, *args, **kwargs):print(fCalling method {func.__name__} on {self})return func(self, *args, **kwargs)return wrapperclass Calculator:def __init__(self, value0):self.value valuemethod_decoratordef add(self, x):self.value xreturn self.valuemethod_decoratordef multiply(self, x):self.value * xreturn self.valuecalc Calculator(10)print(calc.add(5)) # 15print(calc.multiply(2)) # 306. 关于装饰器的应用示例第6点1, 也就是缓存这个装饰器。from functools import lru_cache# 使用内置的lru_cache装饰器lru_cache(maxsize128)def fibonacci(n):if n 2:return nreturn fibonacci(n-1) fibonacci(n-2)# 自定义缓存装饰器def memoize(func):cache {}wraps(func)def wrapper(*args, **kwargs):key str(args) str(kwargs)if key not in cache:cache[key] func(*args, **kwargs)return cache[key]return wrappermemoizedef expensive_computation(x):print(fComputing for {x}...)import timetime.sleep(1)return x * xprint(expensive_computation(5)) # 会打印Computing for 5...print(expensive_computation(5)) # 直接从缓存返回不会打印6.这是一个用于权限验证装饰器的条目。def require_permission(permission):def decorator(func):wraps(func)def wrapper(user, *args, **kwargs):if permission not in user.get(permissions, []):raise PermissionError(fUser lacks {permission} permission)return func(user, *args, **kwargs)return wrapperreturn decoratorclass UserManager:require_permission(admin)def delete_user(self, user, target_user):return fUser {target_user} deleted by {user[name]}require_permission(editor)def edit_content(self, user, content):return fContent edited by {user[name]}admin_user {name: Alice, permissions: [admin, editor]}editor_user {name: Bob, permissions: [editor]}regular_user {name: Charlie, permissions: []}manager UserManager()print(manager.delete_user(admin_user, old_user)) # 正常执行# print(manager.delete_user(editor_user, old_user)) # 抛出PermissionError6.这第3项是关于日志装饰器的一个内容说明。import loggingfrom datetime import datetimelogging.basicConfig(levellogging.INFO)def log_decorator(func):wraps(func)def wrapper(*args, **kwargs):start_time datetime.now()logging.info(fStarting {func.__name__} at {start_time})try:result func(*args, **kwargs)end_time datetime.now()duration (end_time - start_time).total_seconds()logging.info(fFinished {func.__name__} in {duration:.2f}s)return resultexcept Exception as e:logging.error(fError in {func.__name__}: {e})raisereturn wrapperlog_decoratordef process_data(data):import timetime.sleep(0.5)return [x * 2 for x in data]print(process_data([1, 2, 3, 4, 5]))6.第4部分是关于类型检查装饰器的内容。def type_check(**types):def decorator(func):wraps(func)def wrapper(*args, **kwargs):# 检查位置参数for i, (arg, (param_name, expected_type)) in enumerate(zip(args, types.items())):if not isinstance(arg, expected_type):raise TypeError(fArgument {param_name} must be {expected_type}, fgot {type(arg)})# 检查关键字参数for param_name, value in kwargs.items():if param_name in types and not isinstance(value, types[param_name]):raise TypeError(fArgument {param_name} must be {types[param_name]}, fgot {type(value)})return func(*args, **kwargs)return wrapperreturn decoratortype_check(xint, yint)def add_numbers(x, y):return x yprint(add_numbers(5, 3)) # 8# print(add_numbers(5, 3)) # 抛出TypeError7. 关于装饰器的调试工作以及测试环节, 其中需要着重关注的是第7.1小节所涉及的如何对装饰器进行调试这一具体问题的展开说明。def debug_decorator(func):wraps(func)def wrapper(*args, **kwargs):print(f[DEBUG] Calling {func.__name__})print(f[DEBUG] Args: {args})print(f[DEBUG] Kwargs: {kwargs})result func(*args, **kwargs)print(f[DEBUG] {func.__name__} returned: {result})return resultreturn wrapperdebug_decoratordef divide(a, b):return a / bdivide(10, 2)7.2 测试装饰器import unittestdef validate_input(min_value0, max_value100):def decorator(func):wraps(func)def wrapper(value):if not (min_value value max_value):raise ValueError(fValue must be between {min_value} and {max_value})return func(value)return wrapperreturn decoratorvalidate_input(min_value0, max_value100)def process_score(score):return Pass if score 60 else Failclass TestDecorator(unittest.TestCase):def test_valid_score(self):self.assertEqual(process_score(75), Pass)self.assertEqual(process_score(45), Fail)def test_invalid_score(self):with self.assertRaises(ValueError):process_score(150)with self.assertRaises(ValueError):process_score(-10)if __name__ __main__:unittest.main()8. 要避免出现, 在循环里面去定义装饰器的这样的操作行为。# 陷阱在循环中定义装饰器def create_decorators():decorators []for i in range(3):def my_decorator(func):def wrapper():print(fDecorator {i})return func()return wrapperdecorators.append(my_decorator)return decorators # 所有装饰器都会打印Decorator 2# 正确做法使用闭包捕获变量def create_decorator_fixed(n):def my_decorator(func):def wrapper():print(fDecorator {n})return func()return wrapperreturn my_decorator9. 总结装饰器是中强大且灵活的特性它允许我们增强函数的功能, 意味着我们可以做到无需修改原始函数代码, 从而实现代码复用将通用功能封装在装饰器里面。这能够保持代码整洁, 把关注点进行分离, 使代码变得更易于维护。它有助于实现面向切面编程, 比如进行日志处理, 或者执行权限验证等等。掌握装饰器需要理解
企业数字化 ERP 产品动态
相关推荐
MemOS 获取消息接口(POST /product/get/message)完全指南:原始对话历史拉取、参数详解与实战场景 人工智能大模型Agent 记忆AI AgentRAG知识图谱dsh-plugin 【免费下载链接】MemOS Self-evolving memory OS for LLM & AI Agents: ultra-persistent memory, hybrid-retrieval, and cross-task skill reuse, with 35.24% token savings and DeepSeek Harness support. 项目… · 2026/9/24 17:57:39
STM32F103 寄存器方式实现流水灯 STM32F103 寄存器方式实现流水灯 文章目录STM32F103 寄存器方式实现流水灯一、GPIO端口初始化1. 时钟配置2. 设置端口模式二、程序实现1. 流水灯原理2. C语言实现3. 编译和下载时注意的点三、运行效果四、总结五、参考一、GPIO端口初始化
本次实验我没有用 HAL 库,… · 2026/9/24 17:57:33
AI测试工程师面试问什么:我用一万多字总结了13道高频面试题 AI测试这两年炒得很火热,各大公司纷纷宣布引入AI提升测试效率,招聘岗位也开始出现"AI测试工程师"这个新头衔。但真到了面试环节,很多候选人却发现:网上的AI测试资料要么停留在概念层面,要么就是工具教程&… · 2026/9/24 17:57:32
插入排序与希尔排序:原理、C语言实现与性能对比 插入排序与希尔排序排序算法是数据结构与算法里绕不开的基础课,而插入排序和希尔排序这对“师徒组合”尤其值得花点时间搞清楚。插入排序是很多人学习排序时最早接触的几种算法之一,思路直观到几乎不需要背代码;希尔排序则是插入排序的升级改… · 2026/9/24 18:36:37
PoolFormer实战:用平均池化替代注意力的图像分类模型 简介:面向图像分类与Transformer架构研究者,这套PoolFormer实战项目以MetaFormer通用框架为基础,通过简单非参数Pooling算子充当极弱token混合器,清晰展示了PoolFormer如何以较低算力实现有竞争力的图像分类效果。资源完整演示了从… · 2026/9/24 18:36:31
智能家居选购指南:不看品牌排名,先看这四个关键指标 “智能家居哪个牌子好”几乎是我被问到最多的问题。每当有人拿着某平台的年度品牌榜单跑来问我“照这个买行不行”,我都会先说一句:榜单可以看,但别照单全收。这几年我一直在帮朋友、带客户做全屋智能的选型与调试,自己也前前后后… · 2026/9/24 18:36:31
Kong限流插件深度解析:local与redis策略选型与实战 最近一次接手公司 API 网关的限流改造,让我真正把 Kong 的 rate-limiting 插件从头到尾研究了一遍。之前一直用的是默认策略,网关是单节点部署,感觉一切正常。后来业务量上来了,网关横向扩到三台,结果限流数字完全对不… · 2026/9/24 18:36:31
Kong网关限流插件local与redis策略对比:从原理到生产配置全解析 Kong网关做过流量治理的人,对rate-limiting插件应该都不陌生。它配置简单,一个插件绑定到路由上,加两个参数就能把接口限流跑起来,但真正到了多节点部署、线上压测的时候,很多人会突然发现——咦,限流怎么不… · 2026/9/24 18:36:31
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44