如何在动态父类名场景下从子类实例获取父类名称改写属性
如何动态访问父类的名称改写属性?
Python中,双下划线开头的私有属性会被名称改写机制处理,变成_类名__属性名的形式,以此实现封装。如果要动态访问父类的这类属性,而不硬编码父类名称,可以按以下方式实现:
方案1:针对单一直接父类
通过子类的__bases__属性获取直接父类,再构造改写后的属性名:
class Foo: def __init__(self): self.__is_init = False async def init(self): self.__is_init = True class Bar(Foo): pass bar = Bar() # 获取子类的直接父类 parent_cls = bar.__class__.__bases__[0] # 构造名称改写后的属性名 target_attr = f"_{parent_cls.__name__}__is_init" # 获取属性值 is_init = getattr(bar, target_attr) print(is_init) # 输出: False
方案2:支持多重继承场景
如果子类继承了多个父类,可以遍历所有父类,检查并获取目标属性:
def get_parent_private_attr(instance, raw_attr_name): """从实例的父类中获取指定的私有属性""" for base_cls in instance.__class__.__bases__: modified_attr = f"_{base_cls.__name__}__{raw_attr_name}" if hasattr(instance, modified_attr): return getattr(instance, modified_attr) raise AttributeError(f"未找到包含私有属性__{raw_attr_name}的父类") # 使用示例 bar = Bar() print(get_parent_private_attr(bar, "is_init")) # 输出: False
更优雅的替代方案
Python设计名称改写的初衷是为了封装,直接访问私有属性违背设计原则。更合理的方式是让父类提供公开的访问接口:
class Foo: def __init__(self): self.__is_init = False async def init(self): self.__is_init = True # 提供公开方法获取私有属性值 def is_initialized(self): return self.__is_init class Bar(Foo): pass bar = Bar() print(bar.is_initialized()) # 输出: False
内容的提问来源于stack exchange,提问作者user9608133
相关产品推荐
相关产品推荐

