如何正确编写带Getter/Setter的Python抽象类及其子类?
问题分析
核心错误点
- 抽象类的
titlegetter仅写了pass,既没有定义属性存储逻辑,也没有强制子类实现getter的约束(原代码仅给setter添加了@abstractmethod)。 - 子类的
title方法没有实际存储属性值,仅做打印操作,即便加上父类的setter装饰器,也未给实例绑定存储变量(比如self._title),导致赋值后无法获取有效内容。 - 子类使用
@BookPrototype.title.setter装饰器是错误操作:子类需先实现自身的@propertygetter,再用自身的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
正确的子类实现
子类需完成三个关键操作:
- 定义存储属性的实例变量(比如
self._title); - 用
@property装饰getter方法,返回存储的变量; - 用自身的
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
相关产品推荐
相关产品推荐

