鱼C论坛

 找回密码
 立即注册
查看: 66|回复: 3

第46讲课后作业,装饰器拆开是怎么写

[复制链接]
发表于 前天 17:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. def type_check(correct_type):
  2.     def outer(func):
  3.         def inner(arg):
  4.             if(type(arg) == correct_type):
  5.                 return func(arg)
  6.             else:
  7.                 return "参数类型错误!"
  8.         return inner
  9.     return outer
  10.    
  11.    
  12. print("<<<--- 测试整数 --->>>")
  13.    
  14. @type_check(int)
  15. def double(x):
  16.     return x * 2
  17.    
  18. print(double(2))      # 这里打印结果应该是 4
  19. print(double("2"))    # 这里打印结果应该是 “参数类型错误”
  20.    
  21. print("\n<<<--- 测试字符串 --->>>")
  22.    
  23. @type_check(str)
  24. def upper(s):
  25.     return s.upper()
  26.    
  27. print(upper('I love FishC.'))   # 这里打印结果应该是 I LOVE FISHC
  28. print(upper(250))               # 这里打印结果应该是 “参数类型错误”
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 前天 17:02 | 显示全部楼层
问题分析:
装饰器的本质是函数嵌套调用。当使用 @decorator 语法糖时,实际上是在将被装饰函数作为参数传递给装饰器。拆开写可以帮助理解执行流程。


拆解步骤:

  • 原装饰器写法:
    1. @type_check(int)
    2. def double(x):
    3.     return x * 2
    复制代码

  • 等价的手动装饰写法:
    1. def double(x):            # 原始函数定义
    2.     return x * 2

    3. # 手动装饰过程
    4. double = type_check(int)(double)  # 分两步执行:
    5.                                   # 1. type_check(int) 返回 outer 函数
    6.                                   # 2. outer(double) 返回 inner 函数
    复制代码



完整拆解验证代码:

  1. # 定义装饰器工厂
  2. def type_check(correct_type):
  3.     def outer(func):
  4.         def inner(arg):
  5.             if type(arg) == correct_type:
  6.                 return func(arg)
  7.             else:
  8.                 return "参数类型错误!"
  9.         return inner
  10.     return outer

  11. # 原始函数定义
  12. def _double(x):
  13.     return x * 2

  14. def _upper(s):
  15.     return s.upper()

  16. # 手动应用装饰器
  17. double = type_check(int)(_double)  # 先传参int,再传函数_double
  18. upper = type_check(str)(_upper)    # 先传参str,再传函数_upper

  19. # 测试验证
  20. print(double(2))      # 输出 4
  21. print(double("2"))    # 输出 "参数类型错误!"
  22. print(upper('FishC')) # 输出 "FISHC"
  23. print(upper(250))     # 输出 "参数类型错误!"
复制代码


关键理解点:
  • 装饰器工厂 type_check(int) 先执行,返回 outer 函数
  • 外层闭包保存了类型参数 correct_type=int/str
  • 最终被调用的是 inner 函数,它包裹了原始函数


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 17:14 | 显示全部楼层
“拆开” 是什么意思?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 前天 20:22 | 显示全部楼层
本帖最后由 jackz007 于 2025-5-13 21:59 编辑
  1. @type_check(int)
  2. def double(x):
复制代码

    用户函数 double() 被 type_check(int) 装饰,当这样调用函数 double() 时:
  1. k = double(x)
复制代码

    Python 将实际执行这一句:
  1. k = type_check(int)(double)(x)
复制代码

  1. @type_check(str)
  2. def upper(s):
复制代码

    用户函数 upper() 被 type_check(str) 装饰,当这样调用函数 upper() 时:
  1. k = upper(s)
复制代码

    Python 将实际执行这一句:
  1. k = type_check(str)(upper)(s)
复制代码


        本例不使用装饰器的完整代码如下:

  1. def type_check(correct_type):
  2.     def outer(func):
  3.         def inner(arg):
  4.             if(type(arg) == correct_type):
  5.                 return func(arg)
  6.             else:
  7.                 return "参数类型错误!"
  8.         return inner
  9.     return outer
  10.    
  11. # @type_check(int)                             # 必须先注释掉装饰器定义
  12. def double(x):
  13.     return x * 2

  14. # @type_check(str)                             # 必须先注释掉装饰器定义
  15. def upper(s):
  16.     return s . upper()


  17. # 下面的代码模拟装饰器机制

  18. print("<<<--- 测试整数 --->>>")
  19. print(type_check(int)(double)(2))              # print(double(2))                # 这里打印结果应该是 4
  20. print(type_check(int)(double)("2"))            # print(double("2"))              # 这里打印结果应该是 “参数类型错误”
  21. print("\n<<<--- 测试字符串 --->>>")
  22. print(type_check(str)(upper)('I love FishC.')) # print(upper('I love FishC.'))   # 这里打印结果应该是 I LOVE FISHC
  23. print(type_check(str)(upper)(250))             # print(upper(250))               # 这里打印结果应该是 “参数类型错误”
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-15 17:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表