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

Python:如何阻止类实例的属性被外部修改?

如何阻止直接修改Python类实例的属性?

这个问题的核心在于Python默认的类属性是公开可直接修改的,要阻止外部直接赋值修改data属性,我们可以通过私有属性+只读属性装饰器的方式来实现,同时还能避免外部通过引用修改内部数据的问题。

解决方案一:使用私有属性与@property只读访问

Python中,以双下划线__开头的属性会触发名称修饰(name mangling),变成_类名__属性名的形式,虽然不是绝对的“私有”,但能有效阻止常规的外部直接访问和赋值。配合@property装饰器,我们可以提供只读的访问接口,同时返回数据的副本,彻底避免外部修改内部状态。

修改后的完整代码如下:

class Matrix: 
    def __init__(self, data): 
        # 用私有属性存储原始数据,避免外部直接访问
        self.__data = data 
    def __str__(self): 
        display = [] 
        for row in self.__data: 
            display.append(str(row)) 
        return '\n'.join(display)
    
    @property
    def data(self):
        # 返回每行的副本,确保外部拿到的不是内部数据的引用
        return [row.copy() for row in self.__data]

测试效果

运行以下代码验证:

a = Matrix([[1, 2], [3, 4]])
print(a.data)  # 输出: [[1, 2], [3, 4]]

# 尝试直接赋值会触发AttributeError
# a.data = [[0,0],[0,0]]  # 这行代码会报错:AttributeError: can't set attribute

# 即使修改返回的副本,也不会影响内部的原始数据
temp = a.data
temp[0][0] = 99
print(a.data)  # 输出依然是: [[1, 2], [3, 4]]

为什么这样有效?

  1. 私有属性__data:Python会自动把__data重命名为_Matrix__data,外部代码无法直接通过a.__data访问,常规赋值操作a.data = ...会因为没有对应的setter而报错。
  2. 返回数据副本:如果只是返回self.__data,外部虽然不能重新赋值,但可以通过列表的可变特性修改元素(比如a.data[0][0] = 0)。返回row.copy()的列表副本,能彻底切断外部与内部数据的引用关联。

备选方案:使用冻结数据类(适合简单场景)

如果你的类不需要复杂的内部逻辑,也可以用dataclasses的冻结特性来创建不可变对象:

from dataclasses import dataclass, field
from typing import List

@dataclass(frozen=True)
class Matrix:
    data: List[List[int]] = field(default_factory=list)
    
    def __str__(self):
        display = []
        for row in self.data:
            display.append(str(row))
        return '\n'.join(display)

此时尝试a.data = [[0,0],[0,0]]会触发FrozenInstanceError,不过要注意:冻结数据类只是阻止属性重新赋值,内部的列表依然是可变的,如果要完全不可变,需要把内部元素也改成不可变类型(比如tuple)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:02:59