子类重写__new__返回父类实例是否属于Python反模式?
问题1:这是否是个糟糕的思路?如果是的话,正确的实现方式是什么?
是非常糟糕的思路,完全违反了面向对象继承的基本约定:子类的实例应当满足isinstance(子类实例, 子类) == True,你当前的实现中isinstance(Teacher("Bob"), Teacher)会返回False,会给所有读代码的人造成严重的认知混淆,后续维护极容易出bug。
你要实现「固定部分参数创建父类实例」的需求,有两种完全无副作用、符合直觉的实现方式:
- 普通工厂函数实现:和你原有调用语法完全一致,类型也完全正确
class Person: def __init__(self, name: str, profession: str): self.name = name self.profession = profession # 直接把Teacher定义为工厂函数,调用逻辑和你原写法没有任何区别 def Teacher(name: str) -> Person: return Person(name=name, profession="teacher") rita = Person("Rita", profession="surgeon") bob = Teacher("Bob") - 父类类方法实现:适合同类固定参数创建的场景比较多的情况,代码更聚合
from typing import Self class Person: def __init__(self, name: str, profession: str): self.name = name self.profession = profession @classmethod def create_teacher(cls, name: str) -> Self: return cls(name=name, profession="teacher") bob = Person.create_teacher("Bob")
问题2:这是已被公认的设计模式吗?
不是,这种实现属于典型的反模式。你要实现的需求本身属于工厂模式的适用场景,但常规的工厂模式不会通过「继承+重写__new__返回父类实例」这种反直觉的方式实现,只会用上面提到的工厂函数、类方法工厂、独立工厂类这几种标准实现。
问题3:常用的类型检查工具能否正确处理这种实现?
完全不能。你示例里已经提到了,类型检查器会默认认为Teacher("Bob")返回的是Teacher类型,但实际运行时返回的是Person类型,会出现大量类型不匹配的隐患:
- 如果你后续给
Teacher类新增了独有的方法,类型检查器会允许你在bob上调用这个方法,但实际运行会直接抛出属性不存在的异常 - 如果你代码里有
isinstance(bob, Teacher)的判断,运行时永远为假,但类型检查器不会给出任何提示 - 部分开启严格模式的类型检查工具(比如mypy strict模式)可能会直接对你重写
__new__的代码抛出告警,但默认配置下只会静默留下类型隐患
内容的提问来源于stack exchange,提问作者LondonRob
相关产品推荐
相关产品推荐

