为何已定义的属性值未正常输出?Python代码问题求助
问题分析:@property中访问父类属性输出None的原因
复现代码
class PageElement: def __init__(self, a, b): self.a = a self.x = b @property def prop(self): print(f"{self.x}") return 1 class Tag(PageElement): def __init__(self, a, b): self.a = a self.b = b def __getattr__(self, x): self.x = x print("Tag.getattr was invoked") t = Tag(3, 4) print(t.prop)
实际输出
Tag.getattr was invoked None 1
核心原因拆解
问题出在__getattr__的返回规则和属性访问的执行顺序上:
- 实例无初始
x属性:Tag的__init__没有调用父类的__init__,所以创建t后,实例仅包含a=3、b=4,不存在x属性。 - 访问
t.prop触发属性查找:prop是父类的@property方法,执行其函数体时需要读取self.x。 __getattr__被调用但无返回值:因为t没有x属性,Python会调用Tag的__getattr__('x')。你在方法里设置了self.x='x'并打印提示,但**__getattr__默认返回None(无return语句时)**。self.x的取值是__getattr__的返回值:Python中,当__getattr__处理属性访问时,属性的取值直接等于该方法的返回值。所以这次print(f"{self.x}")打印的是__getattr__返回的None——虽然你在方法里给t设置了x='x',但这个赋值不影响本次访问的结果。- 后续实例才拥有
x属性:执行完__getattr__后,t.__dict__里确实会出现x='x',但这是在本次self.x访问完成后才生效的,对之前的打印没有作用。
验证与修复
如果给__getattr__加上返回值,就能得到预期输出:
def __getattr__(self, x): self.x = x print("Tag.getattr was invoked") return self.x # 添加返回值
此时输出变为:
Tag.getattr was invoked x 1
另外,若希望Tag实例初始化时就继承父类的x属性,也可以在Tag的__init__中调用super().__init__(a, b),这样就不会触发__getattr__了。
内容的提问来源于stack exchange,提问作者Neo Anderson
相关产品推荐
相关产品推荐

