在TCL OO中让父类变量对子类只读且禁止直接访问
嘿,这个需求我刚好有成熟的解决方案!要让子类完全碰不了父类的bar属性,不管是读还是写都直接报错,咱们可以利用Python的魔法方法做属性拦截,彻底杜绝子类覆盖同名变量的问题。
完整实现代码
class Foo: def __init__(self): # 用内部变量存储实际值,避免和要保护的`bar`名称冲突 self._bar = "父类初始值" def __getattribute__(self, name): # 拦截子类对`bar`的读取操作 if name == "bar" and type(self) is not Foo: raise AttributeError("禁止访问父类的bar属性!") # 父类自身访问则正常返回 return super().__getattribute__(name) def __setattr__(self, name, value): # 拦截子类对`bar`的赋值操作 if name == "bar" and type(self) is not Foo: raise AttributeError("禁止修改父类的bar属性!") # 正常处理其他属性和父类自身的属性赋值 super().__setattr__(name, value) # 父类可以通过这个方法安全访问bar的值 def get_bar(self): return self._bar class Moo(Foo): def __init__(self): super().__init__() # 尝试在子类里定义同名变量?不存在的,赋值直接报错 # self.bar = "子类值" # 取消注释会触发错误
效果测试
if __name__ == "__main__": # 父类实例可以正常操作 foo = Foo() print("父类访问bar:", foo.get_bar()) # 输出:父类访问bar: 父类初始值 foo._bar = "父类更新值" print("父类更新后bar:", foo.get_bar()) # 输出:父类更新后bar: 父类更新值 # 子类实例访问bar直接报错 moo = Moo() try: print(moo.bar) except AttributeError as e: print("子类读取bar报错:", e) # 输出:子类读取bar报错: 禁止访问父类的bar属性! try: moo.bar = "子类尝试赋值" except AttributeError as e: print("子类赋值bar报错:", e) # 输出:子类赋值bar报错: 禁止修改父类的bar属性!
原理说明
- 属性拦截:通过重写
__getattribute__(拦截属性读取)和__setattr__(拦截属性赋值)两个魔法方法,对bar属性的访问进行检查。 - 实例类型判断:用
type(self) is not Foo来区分当前实例是父类本身还是子类,只有子类访问bar时才触发报错。 - 内部变量存储:父类用
_bar存储实际值,避免和对外的bar名称冲突,同时保证父类自身可以正常操作数据。 - 字节码层面有效:不管是直接写代码还是调用编译后的字节码,属性访问都会经过这两个魔法方法,完全杜绝子类覆盖同名变量的风险。
内容的提问来源于stack exchange,提问作者user1134991
相关产品推荐
相关产品推荐

