如何通过实现__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
相关产品推荐
相关产品推荐

