如何在子类中仅重写父类函数的单行代码而无需复制整个函数?
问题描述
现有如下代码:
@dataclasses.dataclass class A(): def parsing_tasks(self): self.start = start(self) .... self.end = end_stage(self) @dataclasses.dataclass class B(A): def DAG(self): dag = self.parsing_tasks() return dag @dataclasses.dataclass class C(B): def parsing_tasks(self): # 此处重写了A类的parsing_tasks方法 self.start = start(self) ... self.end = end_stage_by_mic(self) def end_stage(dag_def: B): .... return end def end_stage_by_mic(dag_def: A): .... return end_by_mic
需求是在C类中实现self.end = end_stage_by_mic(self),但parsing_tasks函数逻辑冗长,仅为修改一行代码就重写整个函数过于冗余。常规的基类参数化方案因end_stage和end_stage_by_mic的参数类型分别为B和A,迁移会引发其他问题,因此寻求其他解决思路。
可行解决思路
思路1:复用父类方法后覆盖结果
如果parsing_tasks的其他逻辑无需修改,仅需替换最终的self.end值,可直接调用父类的parsing_tasks方法,之后覆盖self.end:
@dataclasses.dataclass class C(B): def parsing_tasks(self): super().parsing_tasks() # 执行父类的完整逻辑 self.end = end_stage_by_mic(self) # 仅替换end值
这种方式最简单直接,无需改动基类,也避免了代码冗余。
思路2:提取可变逻辑为类方法
在基类中把获取end值的逻辑提取为独立方法,子类仅重写该方法即可:
@dataclasses.dataclass class A(): def parsing_tasks(self): self.start = start(self) .... self.end = self._get_end_value() # 调用提取后的方法 def _get_end_value(self): # 基类默认调用end_stage,B作为A的子类,实例传入end_stage符合参数要求 return end_stage(self) @dataclasses.dataclass class C(B): def _get_end_value(self): return end_stage_by_mic(self) # 子类重写该方法,替换为目标逻辑
此方法将可变部分与固定逻辑解耦,后续若有其他子类需要修改end值,只需重写_get_end_value即可。
思路3:通过dataclass参数化配置结束函数
利用dataclass的字段特性,将结束函数作为类的可配置参数,基类中直接使用该参数:
from typing import Callable @dataclasses.dataclass class A(): end_func: Callable[["A"], any] = end_stage # 默认使用end_stage def parsing_tasks(self): self.start = start(self) .... self.end = self.end_func(self) @dataclasses.dataclass class C(B): end_func: Callable[["A"], any] = end_stage_by_mic # 子类替换为目标函数
需要注意:若end_stage要求参数为B类型,可调整其类型注解为Union[A, B]或直接A(因为B是A的子类,类型兼容),避免类型检查报错。
思路4:调整结束函数的类型注解(若允许)
如果可以修改end_stage的类型注解,将其参数改为基类A,那么直接使用基类参数化方案即可:
# 修改end_stage的类型注解 def end_stage(dag_def: A): .... return end # 之后在基类或子类中直接指定结束函数 @dataclasses.dataclass class A(): end_func: Callable = end_stage # parsing_tasks逻辑同上... @dataclasses.dataclass class C(B): end_func: Callable = end_stage_by_mic
这种方式最简洁,但前提是修改end_stage的类型注解不会影响其他依赖该函数的逻辑。
内容的提问来源于stack exchange,提问作者jikf
相关产品推荐
相关产品推荐

