You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中<instance>.<property> += v会调用属性的setter吗?

为什么对Python属性调用__iadd__会触发setter?

首先看定义的类代码:

class TameWombat:
    def __init__(self):
        self.stomach = []
    def __iadd__(self, v):
        self.stomach += v
        return self

class Fred:
    def __init__(self):
        self._pet = TameWombat()
    @property
    def wombat(self):
        return self._pet
    @wombat.setter
    def wombat(self, v):
        raise ValueError("Fred只想要这只特定的袋熊,谢谢。")

尝试对属性调用__iadd__方法时出现异常:

>>> fred = Fred()
>>> 
>>> fred.wombat += '美味的食物'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in wombat
ValueError: Fred只想要这只特定的袋熊,谢谢。

明明这里的+=应该作用于getter返回的袋熊实例,而不是直接修改Fred的属性,为什么会触发setter?


原因解析

Python对+=这类增强赋值运算符的处理是固定流程:

  • 第一步:调用属性的getter,获取当前值,记为临时变量temp = fred.wombat
  • 第二步:执行temp = temp.__iadd__('美味的食物'),哪怕你的__iadd__返回了实例本身,Python也不会跳过后续步骤
  • 第三步:尝试调用属性的setter,把temp重新赋值给fred.wombat,也就是fred.wombat = temp

哪怕temp和原来的袋熊实例是同一个对象,Python也会严格执行第三步的赋值操作,所以就触发了setter里的异常。

解决办法

有两种可行的处理方式:

  • 如果不需要限制外部替换Fred的袋熊实例,直接删掉setter方法即可。这样第三步找不到setter,就不会执行赋值,自然不会报错
  • 要保留setter的限制的话,直接调用__iadd__方法代替+=语法:
    fred.wombat.__iadd__('美味的食物')
    
    这种方式只会执行前两步,不会触发后续的赋值操作,也就不会触发setter。

内容的提问来源于stack exchange,提问作者Marnanel Thurman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:55:18