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

为何Python中仅含Getter的列表属性可修改元素?

为什么仅定义Getter的属性仍能修改列表元素?

这是因为你混淆了修改属性的绑定关系和修改可变对象的内部状态,两者完全是两回事:

  1. @property的限制只针对“属性绑定”
    当你尝试直接给li.l赋值(比如li.l = [1,2,3]),这属于修改属性的绑定,此时因为没有定义setter,Python才会抛出AttributeError: can't set attribute,这符合你最初的预期。

  2. 你实际做的是修改可变对象的内部状态
    li.l[0] = "this shouldn't work"的执行逻辑是:

    • 先通过getter获取__a_private_attribute指向的列表对象(返回的是该列表的引用,不是副本)
    • 调用列表的__setitem__方法修改索引0的元素
      这个过程没有改变li.l指向的对象,只是改变了对象本身的内容——而@property的getter不会限制你对返回对象的操作,尤其是像列表这种可变对象。

如何阻止这种修改?

如果要彻底防止外部修改内部列表的内容,你需要在getter中返回列表的副本,而不是原对象的引用:

class AList:
    def __init__(self, l):
        self.__a_private_attribute = l.copy()  # 初始化时也存副本,避免外部传入的列表直接影响内部

    @property
    def l(self):
        return self.__a_private_attribute.copy()  # 返回副本,外部修改不会影响原属性


if __name__ == '__main__':
    li = AList([0])
    li.l[0] = "this shouldn't work"
    print(li.l)  # 输出 [0],修改的只是副本,原属性不受影响

另外补充:Python的私有属性(双下划线开头)只是做了名字修饰(变成_AList__a_private_attribute),本质上还是能通过特殊方式访问,但这个问题的核心和私有性无关,完全是可变对象的特性导致的。

内容的提问来源于stack exchange,提问作者Jakub Watson-Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:40:25