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

Python中property与__getattr__共存及阻止新增属性问题

解决方案

要实现仅允许在实例化时通过指定参数添加额外可读写属性,同时禁止后续新增自定义属性,可以通过以下方式修改代码,同时兼容已有的property:

class Person:
    __slots__ = ["_name", "_allowed_extra_attr"]

    def __init__(self, name, extra_arg):
        # 记录允许的额外属性名
        self._allowed_extra_attr = extra_arg
        # 初始化内置属性
        self._name = name
        # 初始化额外属性
        setattr(self, extra_arg, None)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    def __setattr__(self, name, value):
        # 允许设置的属性:内置私有属性、允许的额外属性
        allowed_attrs = {self._allowed_extra_attr, "_name", "_allowed_extra_attr"}
        if name in allowed_attrs:
            super().__setattr__(name, value)
        else:
            raise AttributeError(f"Cannot set attribute '{name}': only pre-defined attributes are allowed")

# 测试示例
person = Person("gribouille", "hello")
print(person.name)  # 正常读取property
person.name = "new_name"  # 正常修改property
print(person.name)

person.hello = "world"  # 正常修改额外属性
print(person.hello)

# 尝试新增自定义属性会报错
try:
    person.custom_attribute = "value"
except AttributeError as e:
    print(e)  # 输出: Cannot set attribute 'custom_attribute': only pre-defined attributes are allowed

关键改动说明

  1. 调整__slots__:移除__dict__,新增_allowed_extra_attr用于存储实例化时指定的额外属性名。这样默认会阻止所有未在__slots__中声明的属性,避免用户随意新增。
  2. 重写__setattr__:
    • 仅允许设置三类属性:_name(对应name property的底层存储)、_allowed_extra_attr(记录允许的额外属性名)、以及实例化时指定的extra_arg属性。
    • 其他属性设置直接抛出AttributeError,阻止自定义属性添加。
  3. 兼容property:name的setter本质是修改_name,而_name在允许的属性列表中,因此不会和__setattr__冲突。

扩展提示

如果需要支持多个额外属性,只需将extra_arg改为列表/元组,在__init__中遍历初始化,并在__setattr__中判断属性是否在允许的列表里即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:45:52