Python子类__init__:重复父类参数还是用**kwargs?求最佳实践
子类继承中
__init__方法参数传递的最佳实践问题 假设你要继承如下基类:
class Shape: def __init__(self, x: float, y: float): self.x = x self.y = y
在子类的__init__方法中处理父类参数,常见有两种模式:
第一种:完全重写父类接口
class Circle(Shape): def __init__(self, x: float, y: float, radius: float): super().__init__(x=x, y=y) self.radius = radius
第二种:通过**kwargs传递父类参数
仅定义子类特有的参数,将剩余参数通过**kwargs传递给父类的__init__:
class Circle(Shape): def __init__(self, radius: float, **kwargs): super().__init__(**kwargs) self.radius = radius
两种方式都有明显缺点,想了解业内的标准或最佳实践是什么。
完全重写接口的方式在Python继承示例中很常见,但如果子类化的是接口复杂的类(如pandas.DataFrame或logging.Logger),这种方式会非常繁琐;而且父类接口变更时,所有子类的接口都要同步修改,不符合*DRY(Don't Repeat Yourself)*原则。这种情况下通常会选择**kwargs方式。
但**kwargs方式会让用户不清楚实际需要哪些必填参数。比如在上述示例中,用户可能会写出:
circle = Circle() # Argument missing for parameter "radius"
IDE(或mypy、Pyright)会提示缺少radius参数,用户修改为:
circle = Circle(radius=5)
此时IDE或类型检查器不再报错,但代码实际运行时会抛出异常:
Traceback (most recent call last): File "foo.py", line 13, in <module> circle = Circle(radius=5) File "foo.py", line 9, in __init__ super().__init__(**kwargs) TypeError: Shape.__init__() missing 2 required positional arguments: 'x' and 'y'
因此陷入两难:要么重复编写父类接口,要么无法通过IDE提前发现子类的错误用法。该如何解决?
调研情况
- 有mypy相关问题与该话题松散相关
- 某Reddit帖子详细讨论了两种方式的优缺点
- 某Stack Overflow问题可能与本问题重复,但针对
__init__方法是否有区别? - 找到了完全重复的Stack Overflow问题,但其答案较晦涩,似乎不属于常规或最佳实践。
内容的提问来源于stack exchange,提问作者LondonRob
相关产品推荐
相关产品推荐

