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

如何在Python类的__init__构造方法中实现只读属性

如何在Python中实现类属性的只读(非方法)?

你希望类实例的full_name属性在初始化后无法被修改,但当前代码里用户可以直接赋值更改。下面是两种简单易懂的实现方式:

方法一:使用@property装饰器(最常用简洁)

这是Python实现只读属性的标准方式,通过装饰器把方法伪装成属性,只提供读取逻辑,不暴露修改入口。

修改后的代码:

class Test:
    def __init__(self, fname: str, lname: str):
        self.first_name = fname
        self.last_name = lname

    @property
    def full_name(self):
        # 直接调用私有方法生成全名
        return self.__private_fullname(self.first_name, self.last_name)

    def __private_fullname(self, name1, name2):
        return name1 + ' ' + name2

# 测试
name = Test('John','Watson')
print(name.full_name)  # 输出 'John Watson'
name.full_name = 'someone else'  # 触发错误:AttributeError: can't set attribute

说明:

  • @property把full_name变成了只读属性,外部访问时就像访问普通实例变量一样,但无法直接赋值。
  • 如果用户尝试修改,Python会直接抛出AttributeError,阻止非法修改。
  • 这种方式代码清晰,符合Python的惯用写法,维护成本低。

方法二:重写__setattr__方法(适合批量控制只读属性)

如果需要同时控制多个只读属性,可以通过拦截属性赋值操作实现:

class Test:
    def __init__(self, fname: str, lname: str):
        self.first_name = fname
        self.last_name = lname
        # 初始化时用父类的__setattr__完成赋值,绕开自己的拦截逻辑
        super().__setattr__('full_name', self.__private_fullname(fname, lname))

    def __private_fullname(self, name1, name2):
        return name1 + ' ' + name2

    def __setattr__(self, name, value):
        # 定义只读属性列表,这里只限制full_name
        read_only_attrs = {'full_name'}
        if name in read_only_attrs:
            raise AttributeError(f"无法修改只读属性 '{name}'")
        # 其他属性正常允许赋值
        super().__setattr__(name, value)

# 测试
name = Test('John','Watson')
print(name.full_name)  # 输出 'John Watson'
name.full_name = 'someone else'  # 触发错误:AttributeError: 无法修改只读属性 'full_name'

说明:

  • 重写__setattr__方法后,所有属性赋值都会经过这个方法,我们可以在这里判断是否是只读属性,若是则抛出错误。
  • 初始化full_name时必须用super().__setattr__,否则会触发自己的拦截逻辑导致初始化失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:54:19