Python访问@property修饰的getter属性为何未抛出属性错误
问题原因解析
先看复现代码:
class A: def __init__(self, f, l): self.first = f self.last = l @property def first(self): return self._first @first.setter def first(self, new): self._first = new a = A("ab", "cd") print(a.first)
你预期会抛出AttributeError,本质是两个认知偏差:
- 误以为类中方法的书写顺序会影响
__init__运行时对类成员的访问 - 误以为调用
first的getter方法时,self._first还未初始化
实际执行逻辑如下:
- 类创建阶段:Python会从上到下执行完类体内的全部代码,把所有方法、类属性都绑定到类对象,类创建完成后才支持实例化操作。也就是说,哪怕你把
first的property定义写在__init__后面,等你执行A("ab", "cd")调用__init__的时候,类属性first已经是同时绑定了getter、setter的完整property对象,不存在访问不到的问题。 - 实例初始化阶段:执行
__init__里的self.first = f时,因为实例本身没有first属性,会向上查找类层面的同名成员,发现是带setter的property,赋值操作会直接被setter拦截,执行self._first = new——这一步就已经给实例绑定了_first属性,把传入的参数值"ab"存储完成,不会生成名为first的实例属性遮挡类上的property。 - 属性读取阶段:执行
print(a.first)时,同样触发property的getter逻辑,此时self._first已经完成初始化,值为"ab",自然可以正常返回,不会抛出异常。
补充:如果删除
__init__里的self.first = f赋值语句,直接访问a.first才会抛出AttributeError,因为此时实例从未通过setter创建过_first属性,getter找不到对应成员就会报错。
内容的提问来源于stack exchange,提问作者arjunsiva
相关产品推荐
相关产品推荐

