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

如何通过实现__setattr__禁止修改Python Fraction类已初始化的实例变量

问题解决方法

核心问题原因

  • 你混淆了类属性字典和实例属性字典:Fraction.__dict__存储的是类维度的成员(类方法、类变量等),num、denom是每个实例独有的属性,存储在实例自身的__dict__属性中,直接访问当前实例的self.__dict__即可,不需要通过类或者新建实例获取。
  • 你在__setattr__中调用Fraction()会触发无限递归:新建实例时会执行__init__给num、denom赋值,赋值操作会再次触发__setattr__,形成死循环。

正确实现代码

你可以通过判断要修改的属性是否为num/denom、且已经存在于当前实例的属性字典中,来实现初始化后禁止修改的逻辑:

class Fraction:
    def __init__(self, num=0, denom=1):
        assert isinstance(num, int), "分子和分母必须为整数"
        assert isinstance(denom, int), "分子和分母必须为整数"
        assert denom != 0, "分母不能为0"
        # 第一次赋值时属性还不在实例__dict__中,会正常写入
        self.num = num
        self.denom = denom
    
    def __setattr__(self, name, value):
        # 仅拦截已存在的num、denom属性的修改操作
        if name in ('num', 'denom') and name in self.__dict__:
            raise NameError("Fraction实例的num、denom属性禁止修改")
        # 直接操作实例__dict__写入属性,不会触发__setattr__递归
        self.__dict__[name] = value

效果测试

# 初始化正常
f = Fraction(1, 2)
print(f.num, f.denom) # 输出 1 2

# 尝试修改属性会抛出异常
f.num = 3 # 触发NameError

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:27:03