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

如何通过装饰器修改类方法代码,实现类仅允许在指定模块内实例化

错误原因
  • 当你定义的类没有显式实现__init__方法时,会继承Python内置object类的__init__,它是C语言实现的method-wrapper对象,本身没有__code__属性,所以访问直接报错
  • 就算你自定义了__init__,__code__是只读的CodeType对象,也不能直接通过加法拼接字节码,你的原始实现思路本身不成立
正确实现方案

我们可以通过包装原有__init__方法,在实例化初始化阶段校验调用者所在模块的方式实现需求,需要用到inspect模块获取调用栈信息:

import inspect

def ModuleSpecificUse(klass=None, module=__name__):
    def decorator(cls):
        # 保存类原有的__init__方法
        original_init = cls.__init__
        def wrapped_init(self, *args, **kwargs):
            # 取调用栈的上一帧,就是实例化类的代码所在位置
            caller_frame = inspect.stack()[1]
            # 获取调用者所在模块的名称
            caller_module_name = caller_frame.frame.f_globals.get("__name__", "")
            if caller_module_name != module:
                raise ValueError("cannot use object")
            # 校验通过后执行原有初始化逻辑
            original_init(self, *args, **kwargs)
        # 替换类的__init__为包装后的方法
        cls.__init__ = wrapped_init
        return cls
    
    # 兼容装饰器带括号和不带括号两种写法
    if klass is None:
        return decorator
    return decorator(klass)
使用示例

你可以按照你原来的方式使用装饰器:

# 假设这段代码定义在foo.py模块中
@ModuleSpecificUse(module="foo")
class C:
    # 类的其他逻辑
    pass
  • 在foo.py模块内实例化C(),运行正常
  • 在其他任意模块导入C后实例化,会抛出ValueError: cannot use object,完全符合你的预期需求

内容的提问来源于stack exchange,提问作者Alan Bagel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:39:03