如何在Python同一数据容器中定义可变、不可变及默认属性?
如何在Python同一数据容器中定义可变、不可变及默认属性?
当然可以实现!针对你提到的Pages类场景——需要first_page是带默认值的不可变属性、current_page是初始化后可变的属性、last_page是初始化后不可变的属性——我们可以通过Python dataclass的特性结合封装技巧来满足需求,下面给你两种实用的方案:
方案一:使用@property实现只读属性
这种方法通过“内部属性+只读属性暴露”的方式,把需要不可变的属性封装起来,只对外提供读取接口,符合Python的封装习惯:
from dataclasses import dataclass @dataclass(slots=True) class Pages: # 用下划线开头标记为内部属性,不建议外部直接访问 _first_page: int = 0 current_page: int _last_page: int # 暴露只读的first_page属性 @property def first_page(self) -> int: return self._first_page # 暴露只读的last_page属性 @property def last_page(self) -> int: return self._last_page
使用时的效果:
page = Pages(current_page=2, last_page=10) print(page.first_page) # 输出 0,正常读取 print(page.last_page) # 输出 10,正常读取 page.current_page = 3 # 可以正常修改可变属性 # 尝试修改不可变属性会报错 page.first_page = 1 # AttributeError: can't set attribute page.last_page = 11 # AttributeError: can't set attribute
方案二:重写__setattr__方法限制属性修改
如果你不想修改属性名称,可以通过重写__setattr__方法,直接拦截对不可变属性的修改操作:
from dataclasses import dataclass @dataclass(slots=True) class Pages: first_page: int = 0 current_page: int last_page: int def __setattr__(self, name: str, value): # 规则:如果是first_page或last_page,且已经初始化过(对象已有该属性),则禁止修改 if name in ('first_page', 'last_page') and hasattr(self, name): raise AttributeError(f"无法修改不可变属性 '{name}'") # 其他属性正常允许修改 super().__setattr__(name, value)
使用时的效果:
page = Pages(current_page=2, last_page=10) page.current_page = 3 # 正常修改 page.first_page = 1 # 抛出 AttributeError: 无法修改不可变属性 'first_page'
补充:其他数据容器的思路
如果你考虑用其他数据容器,也可以参考这些方向:
- 字典(dict):自定义一个字典子类,重写
__setitem__方法,限制特定键的修改; - 元组(tuple):元组本身是不可变的,无法满足既有可变又有不可变属性的需求,不适用;
- Enum:枚举类的成员默认是不可变的,也不适合需要可变属性的场景。
总体来说,dataclass结合上述两种方案是最贴合你需求的实现方式,推荐根据你的代码风格选择合适的方案。
备注:内容来源于stack exchange,提问作者Abdulrahman Sheikho
相关产品推荐
相关产品推荐

