You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python条件装饰器实现问题:指定装饰器时返回函数引用排查

问题分析与修复:条件装饰器返回函数引用而非预期结果

嘿,咱们来拆解下你的代码问题出在哪。当你传入decorator='int'时,控制台输出函数引用而非预期的1,核心问题出在conditional_decorator类的__call__方法里的这一行:

return decorator(self.func(*args, **kwargs))

错误原因拆解

你这里的逻辑完全搞反了:

  1. self.func(*args, **kwargs)会直接执行原函数,返回结果1
  2. 然后你把这个整数结果传给了int_decorator,但int_decorator的设计是接收一个函数作为参数,返回包装后的函数对象
  3. 所以最终返回的是wrapper函数的引用,而不是执行装饰后函数得到的结果

修复方案

正确的逻辑应该是:先给原函数应用对应的装饰器,得到装饰后的函数,再调用这个装饰后的函数并传入参数。同时,我们可以把decorator参数从kwargs中移除,避免它被传递给原函数(如果原函数不需要这个参数的话)。

修正后的完整代码如下:

def int_decorator(func): 
    # checks whether the args passed is of type int. 
    def wrapper(*args, **kwargs): 
        a, b = args 
        if not (isinstance(a, int) and isinstance(b, int)): 
            return 
        return func(*args, **kwargs) 
    return wrapper 

decorator_mapping = { 'int': int_decorator } 

class conditional_decorator(object): 
    def __init__(self, func): 
        self.func = func 
    
    def __call__(self, *args, **kwargs): 
        # 先取出decorator参数,避免传递给原函数
        decorator_name = kwargs.pop('decorator', None)
        decorator = decorator_mapping.get(decorator_name)
        
        if not decorator: 
            # 没有匹配的装饰器,直接调用原函数
            return self.func(*args, **kwargs) 
        
        # 先装饰原函数,再调用装饰后的函数
        decorated_func = decorator(self.func)
        return decorated_func(*args, **kwargs) 

@conditional_decorator 
def func(a, b, *args, **kwargs): 
    return 1 

# 测试用例
print(func(1, 2, decorator='int'))  # 输出1,符合预期
print(func('a', 'b', decorator='int'))  # 输出None,因为参数类型不匹配
print(func(1, 2))  # 输出1,未指定装饰器时正常运行

关键修改点说明

  1. 用kwargs.pop('decorator', None)取出装饰器名称,同时从kwargs中移除该参数,保证原函数只接收它需要的参数
  2. 替换了错误的调用逻辑:先通过decorator(self.func)得到装饰后的函数,再调用这个函数并传入参数*args, **kwargs

这样修改后,无论是指定匹配的装饰器还是不指定,都能得到预期的结果啦。

内容的提问来源于stack exchange,提问作者Praful Bagai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:11:20