一定能行 发表于 2025-5-13 17:01:40

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

def type_check(correct_type):
    def outer(func):
      def inner(arg):
            if(type(arg) == correct_type):
                return func(arg)
            else:
                return "参数类型错误!"
      return inner
    return outer
   
   
print("<<<--- 测试整数 --->>>")
   
@type_check(int)
def double(x):
    return x * 2
   
print(double(2))      # 这里打印结果应该是 4
print(double("2"))    # 这里打印结果应该是 “参数类型错误”
   
print("\n<<<--- 测试字符串 --->>>")
   
@type_check(str)
def upper(s):
    return s.upper()
   
print(upper('I love FishC.'))   # 这里打印结果应该是 I LOVE FISHC
print(upper(250))               # 这里打印结果应该是 “参数类型错误”

FishC 发表于 2025-5-13 17:02:47

问题分析:
装饰器的本质是函数嵌套调用。当使用 @decorator 语法糖时,实际上是在将被装饰函数作为参数传递给装饰器。拆开写可以帮助理解执行流程。

拆解步骤:


[*]原装饰器写法:
@type_check(int)
def double(x):
    return x * 2

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

# 手动装饰过程
double = type_check(int)(double)# 分两步执行:
                                  # 1. type_check(int) 返回 outer 函数
                                  # 2. outer(double) 返回 inner 函数


完整拆解验证代码:

# 定义装饰器工厂
def type_check(correct_type):
    def outer(func):
      def inner(arg):
            if type(arg) == correct_type:
                return func(arg)
            else:
                return "参数类型错误!"
      return inner
    return outer

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

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

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

# 测试验证
print(double(2))      # 输出 4
print(double("2"))    # 输出 "参数类型错误!"
print(upper('FishC')) # 输出 "FISHC"
print(upper(250))   # 输出 "参数类型错误!"

关键理解点:

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


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

player-none 发表于 2025-5-13 17:14:48

“拆开” 是什么意思?

jackz007 发表于 2025-5-13 20:22:39

本帖最后由 jackz007 于 2025-5-13 21:59 编辑

@type_check(int)
def double(x):
    用户函数 double() 被 type_check(int) 装饰,当这样调用函数 double() 时:
k = double(x)
    Python 将实际执行这一句:
k = type_check(int)(double)(x)

@type_check(str)
def upper(s):
    用户函数 upper() 被 type_check(str) 装饰,当这样调用函数 upper() 时:
k = upper(s)
    Python 将实际执行这一句:
k = type_check(str)(upper)(s)

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

def type_check(correct_type):
    def outer(func):
      def inner(arg):
            if(type(arg) == correct_type):
                return func(arg)
            else:
                return "参数类型错误!"
      return inner
    return outer
   
# @type_check(int)                           # 必须先注释掉装饰器定义
def double(x):
    return x * 2

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


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

print("<<<--- 测试整数 --->>>")
print(type_check(int)(double)(2))            # print(double(2))                # 这里打印结果应该是 4
print(type_check(int)(double)("2"))            # print(double("2"))            # 这里打印结果应该是 “参数类型错误”
print("\n<<<--- 测试字符串 --->>>")
print(type_check(str)(upper)('I love FishC.')) # print(upper('I love FishC.'))   # 这里打印结果应该是 I LOVE FISHC
print(type_check(str)(upper)(250))             # print(upper(250))               # 这里打印结果应该是 “参数类型错误”

一定能行 发表于 2025-5-16 00:03:02

player-none 发表于 2025-5-13 17:14
“拆开” 是什么意思?

装饰器原来的样子
页: [1]
查看完整版本: 第46讲课后作业,装饰器拆开是怎么写