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

如何正确编写带Getter/Setter的Python抽象类及其子类?

问题分析

核心错误点

  • 抽象类的title getter仅写了pass,既没有定义属性存储逻辑,也没有强制子类实现getter的约束(原代码仅给setter添加了@abstractmethod)。
  • 子类的title方法没有实际存储属性值,仅做打印操作,即便加上父类的setter装饰器,也未给实例绑定存储变量(比如self._title),导致赋值后无法获取有效内容。
  • 子类使用@BookPrototype.title.setter装饰器是错误操作:子类需先实现自身的@property getter,再用自身的title.setter装饰器绑定setter方法,而非直接复用父类的装饰器。
正确实现方式

修正后的抽象类

抽象类需同时将getter和setter标记为抽象方法,强制子类实现完整的属性访问逻辑:

from abc import ABCMeta, abstractmethod
from copy import deepcopy

class BookPrototype(metaclass=ABCMeta):
    @property
    @abstractmethod
    def title(self):
        """抽象getter,子类必须实现"""
        pass

    @title.setter
    @abstractmethod
    def title(self, val):
        """抽象setter,子类必须实现"""
        pass

    @abstractmethod
    def clone(self):
        pass

正确的子类实现

子类需完成三个关键操作:

  1. 定义存储属性的实例变量(比如self._title);
  2. 用@property装饰getter方法,返回存储的变量;
  3. 用自身的title.setter装饰器实现setter方法,完成赋值逻辑;
class ScienceFiction(BookPrototype):
    def __init__(self):
        self._title = None  # 初始化存储属性的变量

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, val):
        print("Setting title to:", val)
        self._title = val

    def clone(self):
        return deepcopy(self)

测试代码验证

science1 = ScienceFiction()
science1.title = "From out of nowhere"
science2 = science1.clone()
print(science2.title)  # 输出: From out of nowhere
science2.title = "New title"
print(science2.title)  # 输出: New title
print(science1.title)  # 输出: From out of nowhere

原代码不加装饰器能"正常运行"的原因

原子类未使用任何装饰器时,def title(self, val)只是一个普通方法,而Python允许给实例动态添加属性(science1.title = "xxx"是给实例绑定了独立的title属性,和类里的title方法无关)。此时调用print(science1.title)取的是动态添加的实例属性,而非类方法,所以看起来"正常",但这完全违背了抽象类的设计意图——子类根本没有实现抽象的getter/setter,只是利用了Python的动态属性特性。

内容的提问来源于stack exchange,提问作者Life after Guest

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:45:39