如何判断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
相关产品推荐
相关产品推荐

