如何避免使用 Python 继承重新定义默认参数

How to avoid redefining default parameter with Python inheritance

对于简单的继承如

class Base:
  def __init__(self, env: str = 'prod'):
    #...

class Derived(Base):
  def __init__(self, env: str = 'prod'):
    super().__init__(str)

如何避免在两个 classes 中重新定义默认构造函数参数?如果我实例化 Derived() 我确实希望 env 默认为 'prod',我只是不想在多个 class 中重新定义该值。如果我后来决定默认值应该是其他值(例如 'dev'),那么我将不得不更改所有派生的构造函数。

我在想

class Base:
  def __init__(self, env: str = 'prod'):
    #...

class Derived(Base):
  def __init__(self, env: str = None):
    if env is None:
      super().__init__()
    else:
      super().__init__(env)

或者可能将默认值定义为基 class 中的全局常量?这两种方法似乎都过于复杂。什么是 Pythonic 方式?

制作一个class变量。

class Base:
    DEFAULT_ENV = "prod"
    def __init__(self, env=None):
        if env is None:
            env = self.DEFAULT_ENV
        # ...

如果您想在子 class 中使用不同的默认环境,只需覆盖 class 中的 DEFAULT_ENV。如果您想为所有未覆盖它的 classes 更改默认环境,更改 Base 中的 DEFAULT_ENV 即可。

另外,在子 class 中重新定义 __init__ 在 Python 中是可选的,所以如果您不希望子 class 中的 __init__实现与 Base 不同的行为,只需在 subclasses 中省略它。在 class 变量中使用默认环境的另一个优点是,如果您只想在子 class 中更改它,您可以覆盖 class 变量,而不必重新定义 __init__ 在 child !

编辑:如果你觉得 env 决定可能需要一些有趣的事情(比如测试环境变量,或者你的应用程序中的任何其他东西),你可能想要将 default_env 包装在 属性:

class Base:
    DEFAULT_ENV = "prod"
    def __init__(self, env=None):
        if env is None:
            env = self.default_env
        # ...
    @property
    def default_env(self):
        return self.DEFAULT_ENV

以后您可以在 属性 getter.

中实现预期的行为

另一个有利有弊的选择是使用 kwargs。类似于:

class Base:
  def __init__(self, env: str='prod'):
    #...

class Derived(Base):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)