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

如何以Pythonic风格创建工厂方法?附装饰器类实现场景

用工厂方法结合functools.wraps实现装饰器类,限制直接实例化

我需要实现一个装饰器类,要求用户通过工厂方法创建类实例,而非直接调用构造函数实例化。这么做的核心原因是可以借助functools.wraps来包装被装饰的可调用对象,保留其原有的元信息(如函数名、文档字符串等)。

完整实现代码

import functools
import inspect

class Decorator:
    def __init__(self, kallable):
        self._kallable = kallable
        
    @classmethod
    def make_decorator(kls, kallable):
        # 先实例化装饰器类
        wrapped_kallable = kls(kallable)
        # 使用functools.wraps包装实例,保留原可调用对象的元信息
        return functools.wraps(kallable)(wrapped_kallable)
        
    def __call__(self, *args, **kwargs):
        # 获取被装饰函数的名称
        func_name = self._kallable.__name__ 
        
        # 示例前置操作:打印进入函数的日志
        print(f"ENTERING FUNCTION {func_name}")
        
        # 执行原函数
        ret_val = self._kallable(*args, **kwargs)
        
        # 示例后置操作:打印离开函数的日志
        print(f"LEAVING FUNCTION {func_name}")
        
        return ret_val

关键细节说明

  1. 工厂方法的作用:

    • make_decorator作为类方法,是用户创建装饰器实例的唯一入口。它先构造Decorator实例,再用functools.wraps(kallable)对实例进行包装——这一步是直接实例化做不到的,因为functools.wraps需要返回一个包装后的可调用对象,而直接实例化返回的是未处理的类实例,会丢失原函数的元信息。
  2. 装饰逻辑实现:

    • __call__方法是装饰器的核心执行逻辑,这里的打印操作只是示例,你可以替换为任何需要的前置/后置处理(比如参数校验、性能统计、异常捕获等)。
    • 注意:原代码中inspect.currentframe().f_code.co_name会获取到__call__方法的名称,而非被装饰函数的名字,所以建议使用self._kallable.__name__来获取原函数的标识。

使用示例

# 用工厂方法作为装饰器
@Decorator.make_decorator
def calculate_sum(a, b):
    """计算两个数的和"""
    return a + b

# 调用装饰后的函数
result = calculate_sum(3, 5)
print(f"结果:{result}")

# 验证元信息是否保留
print(f"函数名:{calculate_sum.__name__}")
print(f"文档字符串:{calculate_sum.__doc__}")

输出结果:

ENTERING FUNCTION calculate_sum
LEAVING FUNCTION calculate_sum
结果:8
函数名:calculate_sum
文档字符串:计算两个数的和

内容的提问来源于stack exchange,提问作者Toothpick Anemone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:12:26