news 2026/5/15 14:29:31

Python34_装饰器知识

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python34_装饰器知识

Python34_装饰器知识

文章目录

  • Python34_装饰器知识
    • @[toc]
  • 1-核心知识
  • 2-装饰器代码示例
  • 3-辨识函数是否装饰器
    • 一、从代码结构辨识(最核心)
      • 1. 高阶函数特征
      • 2. 返回对象必须是"可调用"的
    • 二、从使用方式辨识
      • 1. `@` 语法糖(显性标识)
      • 2. 手动调用形式(等价写法)
    • 三、从行为模式辨识
      • 1. "透明增强"原则
      • 2. 是否包装(Wrap)原函数
    • 四、实用辨识技巧
      • 技巧 1:用 `inspect` 检查
      • 技巧 2:运行时验证
    • 五、常见混淆情况辨析
    • 六、一句话总结
  • 4-Python装饰器(Decorator)学习笔记
    • 📚 核心概念
      • 简单理解
    • 🎯 装饰器的5个层次
      • 1️⃣ 基础装饰器
      • 2️⃣ 保留元信息 (使用@wraps)
      • 3️⃣ 带参数的装饰器(装饰器工厂)
      • 4️⃣ 参数验证装饰器(类似你的需求)
      • 5️⃣ 实用装饰器示例
    • 🔑 核心要点总结
    • 🚀 运行示例

1-核心知识

  • 装饰器代码代码示例 -> 入参和返回值都【函数】
  • 如何辨识一个函数是装饰器? -> 接收【函数】,返回也必须是【函数】
  • 装饰器的3个层次 -> 基础装饰器+保留元信息+带参数装饰器

2-装饰器代码示例

""" Python装饰器(Decorator)核心概念学习 装饰器本质:是一个接受函数作为参数,并返回一个新函数的函数 """# ==================== 第1层:最基础的装饰器 ====================defmy_decorator(func):"""装饰器本质:包装原函数,添加额外功能"""defwrapper():print("🔵 装饰器:函数调用前")result=func()# 调用原函数print("🔵 装饰器:函数调用后")returnresultreturnwrapper@my_decoratordefsay_hello():print(" Hello World!")# ==================== 第2层:装饰器保留原函数的元信息 ====================fromfunctoolsimportwrapsdefbetter_decorator(func):"""使用wraps保留原函数的名称、文档字符串等信息"""@wraps(func)defwrapper(*args,**kwargs):print(f"🟢 调用函数:{func.__name__}")returnfunc(*args,**kwargs)returnwrapper@better_decoratordefgreet(name):"""向某人打招呼"""returnf"Hello,{name}!"# ==================== 第3层:带参数的装饰器(装饰器工厂) ====================defrepeat(times):""" 带参数的装饰器工厂 返回一个真正的装饰器 """defdecorator(func):@wraps(func)defwrapper(*args,**kwargs):results=[]foriinrange(times):print(f"🔄 第{i+1}次调用")result=func(*args,**kwargs)results.append(result)returnresultsreturnwrapperreturndecorator@repeat(times=3)defsay_hi(name):returnf"Hi,{name}!"# ==================== 第4层:类似你提到的参数验证装饰器 ====================deftool_parameters(parameters):""" 类似TypeScript中 @tool_parameters 的Python实现 验证函数参数的类型和必需性 """defdecorator(func):@wraps(func)defwrapper(**kwargs):# 获取参数定义properties=parameters.get("properties",{})required=parameters.get("required",[])# 验证必需参数forparaminrequired:ifparamnotinkwargs:raiseValueError(f"缺少必需参数: '{param}'")# 验证参数类型forparam_name,param_valueinkwargs.items():ifparam_nameinproperties:expected_type=properties[param_name].get("type")actual_type=type(param_value).__name__# 类型映射type_mapping={"str":str,"int":int,"float":float,"bool":bool,"list":list,"dict":dict}ifexpected_typeintype_mapping:expected_python_type=type_mapping[expected_type]ifnotisinstance(param_value,expected_python_type):raiseTypeError(f"参数 '{param_name}' 类型错误: "f"期望{expected_type}, 实际{actual_type}")# 验证通过,调用原函数returnfunc(**kwargs)returnwrapperreturndecorator# 使用示例@tool_parameters({"type":"object","properties":{"path":{"type":"str"},"count":{"type":"int"}},"required":["path"],})defread_file(path,count=1):"""模拟读取文件"""returnf"读取文件:{path}, 次数:{count}"@tool_parameters({"type":"object","properties":{"user_id":{"type":"int"},"username":{"type":"str"},"active":{"type":"bool"}},"required":["user_id","username"],})defcreate_user(user_id,username,active=True):"""模拟创建用户"""return{"id":user_id,"name":username,"active":active}# ==================== 第5层:带返回值的装饰器 ====================defmeasure_time(func):"""测量函数执行时间"""importtimeimporttimeastime_module@wraps(func)defwrapper(*args,**kwargs):start=time_module.time()result=func(*args,**kwargs)end=time_module.time()print(f"⏱️{func.__name__}执行时间:{end-start:.4f}秒")returnresultreturnwrapper@measure_timedefslow_function():"""模拟耗时操作"""importtime time.sleep(0.1)return"完成"# ==================== 运行所有示例 ====================defmain():print("="*60)print("📚 Python装饰器核心概念学习")print("="*60)print("\n1️⃣ 基础装饰器:")say_hello()print("\n2️⃣ 保留元信息的装饰器:")print(f" 结果:{greet('Alice')}")print(f" 函数名:{greet.__name__}")print(f" 文档:{greet.__doc__}")print("\n3️⃣ 带参数的装饰器(重复3次):")results=say_hi("Bob")print(f" 结果:{results}")print("\n4️⃣ 参数验证装饰器:")# 正确调用try:result=read_file(path="/path/to/file",count=2)print(f" ✅ 正确调用:{result}")except(ValueError,TypeError)ase:print(f" ❌ 错误:{e}")# 缺少必需参数try:result=read_file(count=2)print(f" 结果:{result}")except(ValueError,TypeError)ase:print(f" ❌ 缺少必需参数:{e}")# 类型错误try:result=read_file(path=123)# path应该是字符串print(f" 结果:{result}")except(ValueError,TypeError)ase:print(f" ❌ 类型错误:{e}")print("\n5️⃣ 创建用户(参数验证):")try:user=create_user(user_id=1,username="Tom",active=False)print(f" ✅ 创建成功:{user}")except(ValueError,TypeError)ase:print(f" ❌ 错误:{e}")print("\n6️⃣ 测量执行时间:")result=slow_function()print(f" 结果:{result}")print("\n"+"="*60)print("🎉 学习完成!")print("="*60)if__name__=="__main__":main()

3-辨识函数是否装饰器

辨识一个函数是否是装饰器,可以从代码结构特征使用方式行为模式三个维度来判断。以下是系统化的辨识方法:


一、从代码结构辨识(最核心)

装饰器在代码层面有明确的结构指纹

1. 高阶函数特征

装饰器一定是高阶函数(Higher-Order Function),即:

  • 接收函数作为参数
  • 返回函数(或可调用对象)
# 典型的装饰器结构def装饰器名(func):# ← 参数是一个函数defwrapper(*args,**kwargs):# 增强逻辑...returnfunc(*args,**kwargs)# ← 调用并返回原函数结果returnwrapper# ← 返回一个函数

反例(不是装饰器):

# 虽然接收函数,但返回的不是函数defbad_example(func):return42# 返回 int,不是装饰器# 虽然返回函数,但不接收函数参数defnot_decorator():definner():passreturninner# 工厂函数,不是装饰器

2. 返回对象必须是"可调用"的

装饰器返回的必须是可调用对象(Callable),常见类型:

返回类型示例是否算装饰器
函数return wrapper✅ 是
类的实例(含__call__return CountCalls(func)✅ 是(类装饰器)
类本身return NewClass⚠️ 类装饰器,但较少见
非可调用对象return 42 / None / []❌ 不是

二、从使用方式辨识

1.@语法糖(显性标识)

如果在代码中看到函数定义前有@符号,那它上面的就是装饰器:

@timer# ← timer 是装饰器@log_call# ← log_call 是装饰器defmy_func():pass

注意:@不代表一定"装饰成功"。如果装饰器返回的不是可调用对象,运行时会报错TypeError: 'NoneType' object is not callable

2. 手动调用形式(等价写法)

即使没有@,如果看到这种写法,也说明该函数被当作装饰器使用:

my_func=timer(log_call(my_func))# 等价于叠加装饰器

三、从行为模式辨识

1. "透明增强"原则

真正的装饰器遵循一个核心行为模式:对调用者透明

即:

  • 调用方式不变(参数签名保持一致)
  • 返回值类型不变(或兼容)
  • 函数名和文档应尽量保留(通过@wraps
@timerdefadd(a,b):returna+b# 调用方式完全不变result=add(2,3)# 调用者感知不到被装饰过

如果返回的函数改变了原函数的调用方式(比如要求额外参数),那它更像是一个函数工厂而非装饰器。

2. 是否包装(Wrap)原函数

装饰器的本质是做包装(Wrapper),典型结构是:

defwrapper(*args,**kwargs):# 前置逻辑(可选)result=func(*args,**kwargs)# ← 必须调用原函数# 后置逻辑(可选)returnresult

四、实用辨识技巧

技巧 1:用inspect检查

importinspectdefis_decorator(func):"""粗略判断:是否为高阶函数"""sig=inspect.signature(func)params=list(sig.parameters.values())# 至少有一个参数,且该参数可能是函数(无法100%确定,但可辅助判断)ifnotparams:returnFalse# 检查是否有 return 语句返回内部函数(静态检查有限)returnTrue# 仅作启发式判断

技巧 2:运行时验证

如果你拿到一个函数,不确定它是不是装饰器,可以用测试函数验证

deftest_target():return"original"# 假设 candidate 是你想验证的函数try:result=candidate(test_target)# 检查结果是否是 callable,且调用后行为正常ifcallable(result)andresult()=="original":print("✅ 很可能是装饰器")else:print("❌ 不是装饰器,或破坏了原函数")exceptExceptionase:print(f"❌ 不是装饰器:{e}")

五、常见混淆情况辨析

代码模式是不是装饰器原因
def foo(func): return func⚠️ 退化装饰器结构上符合,但无增强逻辑,称为"空装饰器"或"恒等装饰器"
def foo(func): return lambda: func()✅ 是返回包装函数,符合定义
def foo(): def inner(): pass; return inner❌ 不是不接受函数参数,是普通工厂函数
def foo(func, times=3): ...⚠️ 需看用法如果times有默认值且能直接@foo使用,是;如果必须@foo(3)才是装饰器,那是"装饰器工厂"

六、一句话总结

装饰器的判断标准:一个函数,接收另一个函数作为参数,返回一个可调用对象,且返回的对象在调用时最终会执行原函数的逻辑。

用公式表达:

装饰器 = 高阶函数(接收函数) + 返回可调用对象 + 透明包装原函数

如果你是在阅读第三方库源码时遇到某个函数,按上述结构特征(是否接收函数参数、是否返回函数)和使用场景(是否被@使用)结合判断,就能准确辨识。


4-Python装饰器(Decorator)学习笔记

📚 核心概念

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。

简单理解

原始函数: 煮面条 装饰器: 加个荷包蛋 结果: 荷包蛋面条 (面条 + 蛋 = 增强版面条)

🎯 装饰器的5个层次

1️⃣ 基础装饰器

defmy_decorator(func):defwrapper():# 前置处理result=func()# 后置处理returnresultreturnwrapper@my_decoratordefsay_hello():print("Hello!")

核心逻辑

  • 装饰器是一个函数,接受函数作为参数
  • 返回一个新的函数(wrapper)
  • 在wrapper中调用原函数

2️⃣ 保留元信息 (使用@wraps)

fromfunctoolsimportwrapsdefbetter_decorator(func):@wraps(func)defwrapper(*args,**kwargs):returnfunc(*args,**kwargs)returnwrapper

为什么需要@wraps?

  • 保留原函数的__name____doc__等属性
  • 让调试和反射更准确

3️⃣ 带参数的装饰器(装饰器工厂)

defrepeat(times):"""这返回一个真正的装饰器"""defdecorator(func):defwrapper(*args,**kwargs):for_inrange(times):func(*args,**kwargs)returnwrapperreturndecorator@repeat(times=3)defsay_hi():print("Hi!")

关键理解

  • @repeat(times=3)实际上先调用repeat(3)返回decorator
  • 然后decorator再装饰函数
  • 三层结构:参数函数 → 装饰器 → wrapper

4️⃣ 参数验证装饰器(类似你的需求)

deftool_parameters(parameters):defdecorator(func):defwrapper(**kwargs):# 验证必需参数required=parameters.get("required",[])forparaminrequired:ifparamnotinkwargs:raiseValueError(f"缺少必需参数:{param}")# 验证类型properties=parameters.get("properties",{})forname,valueinkwargs.items():expected_type=properties[name]["type"]# 检查类型...returnfunc(**kwargs)returnwrapperreturndecorator@tool_parameters({"type":"object","properties":{"path":{"type":"str"}},"required":["path"],})defread_file(path):returnf"读取:{path}"

对应你的TypeScript示例

// TypeScript@tool_parameters({"type":"object","properties":{"path":{"type":"string"}},"required":["path"],})# Python(功能等价)@tool_parameters({"type":"object","properties":{"path":{"type":"str"}},"required":["path"],})

5️⃣ 实用装饰器示例

# 测量执行时间defmeasure_time(func):@wraps(func)defwrapper(*args,**kwargs):start=time.time()result=func(*args,**kwargs)end=time.time()print(f"耗时:{end-start:.4f}秒")returnresultreturnwrapper# 缓存结果fromfunctoolsimportlru_cache@lru_cache(maxsize=128)deffibonacci(n):ifn<2:returnnreturnfibonacci(n-1)+fibonacci(n-2)

🔑 核心要点总结

  1. 装饰器 = 高阶函数

    • 接受函数作为参数
    • 返回一个新的函数
  2. 语法糖

    @decoratordeffunc():pass# 等价于func=decorator(func)
  3. 三层结构(带参数时)

    parameter_func(parameters) → decorator → wrapper → original_func
  4. 必须使用@wraps

    • 保留原函数的元信息
    • 方便调试和反射
  5. 常见用途

    • 日志记录
    • 性能测量
    • 参数验证
    • 缓存
    • 权限检查
    • 重试机制

🚀 运行示例

python main.py

查看6个不同层次的装饰器示例,从最基础到类似@tool_parameters的参数验证装饰器。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 14:28:14

基于芒果派MQ Quad的嵌入式视频流媒体系统开发实战

1. 项目概述&#xff1a;当芒果派遇上视频流媒体最近在捣鼓一个挺有意思的项目&#xff0c;核心就是把手头这块小巧的芒果派 MangoPi MQ Quad 开发板&#xff0c;变成一个集视频采集、直播推流和客户端拉流于一身的“全能型选手”。这个想法的初衷很简单&#xff0c;就是想利用…

作者头像 李华
网站建设 2026/5/15 14:23:23

Emacs集成AI编程:gpt.el插件实现GPT模型无缝调用与工作流优化

1. 项目概述&#xff1a;在Emacs中与AI对话的“瑞士军刀”如果你是一个Emacs的重度用户&#xff0c;同时又对AI辅助编程和写作充满兴趣&#xff0c;那么你很可能已经厌倦了在浏览器、终端和编辑器之间来回切换的割裂感。stuhlmueller/gpt.el这个项目&#xff0c;正是为了解决这…

作者头像 李华
网站建设 2026/5/15 14:14:17

构建高性能数据压缩架构:7-Zip-zstd的工程实践与系统设计

构建高性能数据压缩架构&#xff1a;7-Zip-zstd的工程实践与系统设计 【免费下载链接】7-Zip-zstd 7-Zip with support for Brotli, Fast-LZMA2, Lizard, LZ4, LZ5 and Zstandard 项目地址: https://gitcode.com/gh_mirrors/7z/7-Zip-zstd 在现代数据密集型系统中&#…

作者头像 李华
网站建设 2026/5/15 14:13:12

5分钟掌握OBS高级计时器:直播和视频制作的终极时间管理工具

5分钟掌握OBS高级计时器&#xff1a;直播和视频制作的终极时间管理工具 【免费下载链接】obs-advanced-timer 项目地址: https://gitcode.com/gh_mirrors/ob/obs-advanced-timer OBS高级计时器&#xff08;obs-advanced-timer&#xff09;是一款专为OBS Studio设计的强…

作者头像 李华
网站建设 2026/5/15 14:09:20

Tesseract OCR深度实战:从图像到智能文本的工业级解决方案

Tesseract OCR深度实战&#xff1a;从图像到智能文本的工业级解决方案 【免费下载链接】tesseract Tesseract Open Source OCR Engine (main repository) 项目地址: https://gitcode.com/gh_mirrors/tes/tesseract Tesseract OCR作为开源光学字符识别领域的标杆项目&…

作者头像 李华