Python 3.6.5中@property装饰器初始化时触发无限循环问题求助
解决@property装饰器导致的无限循环问题
嘿,我看到你在给自定义Duck类用@property的时候踩了无限循环的坑——这可是刚上手属性装饰器时超级常见的“新手陷阱”,我来帮你捋清楚问题出在哪,以及怎么修复!
问题根源
你现在的代码里,不管是@property修饰的获取方法,还是@name.setter修饰的赋值方法,都直接操作了self.name:
- 当你调用
self.name时,会触发@property的获取逻辑,而获取方法里又写了self.name,这就会无限递归调用获取方法; - 同样,赋值方法里的
self.name = name会触发赋值逻辑本身,也会无限递归下去,最终导致栈溢出报错。
正确的写法示例
我们需要用一个约定俗成的私有变量(通常在变量名前加下划线_)来存储实际的name值,这样在getter和setter里操作这个私有变量,就不会触发属性的get/set逻辑了:
class Duck(object): def __init__(self, name): # 用带下划线的变量存储实际值,这是Python里表示“私有”的约定 self._name = name @property def name(self): print("Quack! My name is", self._name) # 别忘了返回值,不然获取name时会得到None return self._name @name.setter def name(self, name): print("I've decided to change my name into", name, ".") print("So please call me", name, "from now on! Quack!") # 赋值给私有变量,不会触发setter递归 self._name = name
关键细节说明
__init__里初始化的是self._name,而不是self.name:如果直接写self.name = name,会触发setter方法(当然如果初始化时想走setter逻辑也可以这么写,但直接赋值私有变量更高效);- getter方法必须返回
self._name:不然当你执行print(duck.name)时,虽然会打印内容,但输出的结果是None,这肯定不是你想要的; - setter方法赋值给
self._name:这样就不会再次触发setter,完美打破无限循环的闭环。
测试验证效果
你可以跑这段测试代码看看修复后的效果:
# 创建鸭子实例 donald = Duck("Donald") # 调用getter获取名字 donald.name # 修改名字,调用setter donald.name = "Daffy" # 再次获取名字 donald.name
运行后会输出:
Quack! My name is Donald I've decided to change my name into Daffy . So please call me Daffy from now on! Quack! Quack! My name is Daffy
内容的提问来源于stack exchange,提问作者NeoZoom.lua
相关产品推荐
相关产品推荐

