
本文详解 Python 抽象基类(ABC)中定义带 getter 和 setter 的抽象属性的正确方式,重点解决因装饰器顺序错误导致的 AttributeError: attribute '__isabstractmethod__' of 'property' objects is not writable 问题。
本文详解 python 抽象基类(abc)中定义带 getter 和 setter 的抽象属性的正确方式,重点解决因装饰器顺序错误导致的 `attributeerror: attribute '__isabstractmethod__' of 'property' objects is not writable` 问题。
在 Python 的抽象基类(ABC)中,若需声明一个既可读又可写的抽象属性(即同时具备 getter 和 setter),必须严格遵循装饰器的嵌套顺序规则。核心原则是:@abc.abstractmethod 必须作为最内层装饰器(innermost decorator),而 @property 及其 @
这是因为 @abc.abstractmethod 的作用是将方法标记为抽象,并修改其 __isabstractmethod__ 属性;而 property 对象的该属性是只读的。若将 @abc.abstractmethod 写在 @property 外层(如原代码中 @property @abc.abstractmethod),Python 会尝试向 property 实例写入 __isabstractmethod__,从而触发 AttributeError。
✅ 正确写法如下:
import abc
class MyClass(abc.ABC):
@property
@abc.abstractmethod # ✅ 内层:先抽象,再包装为 property
def current_light(self) -> str:
"""当前灯光设置(getter)。"""
...
@current_light.setter
@abc.abstractmethod # ✅ 内层:setter 同样需先抽象
def current_light(self, value: str) -> None:
"""设置当前灯光(setter)。"""
...⚠️ 注意事项:
- 不要颠倒顺序(如 @abc.abstractmethod @property 或 @abc.abstractmethod @current_light.setter),否则必然报错;
- 抽象属性的 getter 和 setter 必须分别标注 @abc.abstractmethod,二者缺一不可;
- 具体子类中实现时,需同时重写 getter 和 setter 方法(且不能遗漏 @property 和 @
.setter 装饰器);
例如,一个合法的子类实现:
class ConcreteClass(MyClass):
def __init__(self):
self._light = "off"
@property
def current_light(self) -> str:
return self._light
@current_light.setter
def current_light(self, value: str) -> None:
if value not in ("on", "off", "dim"):
raise ValueError("Invalid light setting")
self._light = value总结:抽象属性的本质是“抽象的方法对”,而非单一抽象字段。因此,它由两个独立的抽象方法(getter/setter)组成,每个都必须用 @abc.abstractmethod 显式标记,并确保该装饰器处于装饰链最内侧。遵循此规范,即可彻底避免 __isabstractmethod__ 不可写引发的运行时错误。










