如何重写嵌套点运算符?解决__getattr__属性链识别问题
解决自定义类中属性链追踪与自定义返回值的问题
要实现你需要的功能——区分不同的属性链(比如a.b和a.b.c)并返回不同结果,核心思路是用一个「属性追踪器」来记录完整的属性访问路径,直到触发实际求值操作(比如打印、显式转换为字符串)时,再根据完整路径返回对应的值。
下面是具体的实现代码:
class AttrTracker: def __init__(self, path): self.path = path def __getattr__(self, name): # 每次访问新属性,就把属性名追加到路径中,返回新的追踪器 return AttrTracker(self.path + [name]) def __str__(self): # 根据完整的属性路径返回对应结果 if self.path == ['b']: return "hello" elif self.path == ['b', 'c']: return "hi" # 可以继续扩展其他属性链的处理逻辑 else: return f"Unsupported path: {'.'.join(self.path)}" class A: def __getattr__(self, name): # 第一次访问属性时,初始化追踪器,路径为当前属性名 return AttrTracker([name]) # 测试代码 a = A() print(a.b) # 输出"hello" print(a.b.c) # 输出"hi" print(a.x.y.z) # 输出"Unsupported path: x.y.z"
原理说明
- 属性追踪器的作用:
AttrTracker类负责记录每次属性访问的完整路径。当你访问a.b时,A的__getattr__返回一个AttrTracker(path=['b']);当继续访问a.b.c时,这个追踪器的__getattr__会生成一个新的AttrTracker(path=['b','c']),以此类推,每一步都在累积属性路径。 - 延迟求值:只有当需要实际获取值的时候(比如
print会调用对象的__str__方法),才根据完整的属性路径返回对应的结果。这样就能完美区分a.b和a.b.c——它们是两个不同的追踪器实例,各自保存着不同的路径。 - 扩展性:如果需要支持更多属性链的返回值,只需要在
AttrTracker的__str__方法中添加新的判断分支即可。如果需要支持其他操作(比如属性链后调用函数,像a.b.c()),可以重写__call__方法,同样根据self.path来处理逻辑。
额外优化点
如果你希望属性链的结果不仅支持字符串输出,还能作为其他类型使用(比如数值、列表),可以重写更多魔法方法,比如__int__、__float__,或者直接在求值逻辑中返回对应类型的结果。
内容的提问来源于stack exchange,提问作者Dims
相关产品推荐
相关产品推荐

