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

如何判断Python方法是否从其定义的类内部被调用?

方案1:调用栈检测实现(匹配你原有逻辑)

这种方案直接在你现有的__setattr__重写逻辑基础上调整,通过inspect模块检查调用栈的上下文,判断修改请求是否来自类内部:

import inspect

class MyClass:
    __slots__ = ("var",)
    def __init__(self):
        self.var = 0
    def increase_val(self):
        self.var += 1  # 内部调用允许修改
    def __setattr__(self, k, v):
        if k in self.__class__.__slots__:
            # 获取调用__setattr__的上一层栈帧
            caller_frame = inspect.currentframe().f_back
            # 检查调用方是否属于当前类实例的方法
            if 'self' in caller_frame.f_locals and caller_frame.f_locals['self'].__class__ is self.__class__:
                # 内部调用直接放行
                pass
            else:
                # 外部调用禁止修改
                print("Read-only property")
                return
        super().__setattr__(k, v)

注意事项

  • 该方案不需要改动现有类内部的属性读写代码
  • 存在一定性能开销,高频调用__setattr__的场景下不推荐使用
  • 涉及继承时需要调整类判断逻辑,避免子类调用被误拦截

方案2:Python惯用法实现(推荐)

不需要重写__setattr__,用「私有存储属性+公开只读property」的模式实现,完全符合Python的设计规范,稳定性和性能都更好:

class MyClass:
    # 存储用的属性加下划线标记为私有,放入slots
    __slots__ = ("_var",)
    def __init__(self):
        self._var = 0
    def increase_val(self):
        # 内部直接修改私有属性
        self._var += 1
    # 对外暴露只读的var属性
    @property
    def var(self):
        return self._var

效果验证

my_obj = MyClass()
my_obj.increase_val()
print(my_obj.var) # 输出1,正常读取
my_obj.var +=1 # 抛出AttributeError: can't set attribute,外部修改被禁止

优势

  • 无额外性能损耗,执行效率远高于栈检测方案
  • 不存在上下文判断的边界问题,适配继承、嵌套调用等所有场景
  • 符合Python社区的通用编码规范,可维护性更高

内容的提问来源于stack exchange,提问作者Max Shouman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:36:01