Python中@property相关疑问:getter触发与递归原因解析
Python属性访问与递归问题解析
原始代码
class Person(): def __init__(self,name:str,height :float) -> None: #initialize self.__name=name self.height=height @property def name(self) -> str: print("Inside Getter") return self.__name @name.setter def name(self, value): print("New name being set") self.name = value def __repr__(self) -> str: return f"({self.__class__.__name__}:{self.name},{self.height})" p=Person("Sam",180.00) print(p)
问题1:self.name为何触发getter方法?
在上述代码中,当在__repr__方法中以self.name访问属性时,会先调用name的getter方法,再执行__repr__;但用self.__name访问则仅执行__repr__。这是为什么?
代码运行输出
Inside Getter
(Person:Sam,180.0)
解答
这是@property装饰器的特性导致的:
- 给
name方法加上@property后,Python会把这个方法包装成属性的getter访问器。此时通过self.name访问时,Python不会直接查找实例的name属性,而是自动调用你定义的def name(self)方法。 self.__name是Python的**名称改写(name mangling)**机制:双下划线开头的属性会被Python自动重命名为_类名__属性名(这里就是_Person__name),它是实例直接存储的属性,和@property定义的name访问器没有关联,所以访问它不会触发getter。
问题2:修改后为何出现递归错误?
把getter方法改为如下形式(移除双下划线):
def name(self) -> str: print("Inside Getter") return self.name
此时运行会抛出递归错误,请问递归是如何产生的?
报错信息
in name
print("Inside Getter")
RecursionError: maximum recursion depth exceeded while calling a Python object
解答
递归的循环逻辑非常直接:
- 当通过
self.name访问时,因为name被@property修饰,Python会调用这个getter方法。 - 但在getter方法内部,你写了
return self.name,这会再次触发name的getter方法调用。 - 这个调用循环会无限重复,直到达到Python预设的最大递归深度,最终抛出
RecursionError。
简单来说就是:getter方法内部又调用了自身的属性访问,导致无限递归调用。
内容的提问来源于stack exchange,提问作者Armaan Sahoo
相关产品推荐
相关产品推荐

