【问题标题】:How to add required keyword arguments to a derived class's constructor?如何将所需的关键字参数添加到派生类的构造函数?
【发布时间】:2020-01-17 12:47:38
【问题描述】:

我的情况与this question 几乎相同,只是我需要关键字参数。

我想向派生类添加 必需 关键字参数,但不知道如何去做。尝试显而易见的

class ClassA(some.package.Class):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)

class ClassB(ClassA):

    def __init__(self, *args, a, b, c, **kwargs):
        super(ClassB, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

失败,因为我无法为ClassB__init__ 列出类似的参数。和

class ClassB(ClassA):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

当然不起作用,因为没有指定新的关键字。

如何将必需关键字参数添加到派生类的__init__

类似问题:How do I add keyword arguments to a derived class's constructor in Python?

【问题讨论】:

  • 按照该示例,我将尝试提取所需的参数并为缺少的任何参数提高 TypeError
  • 嗯...您编辑了“显而易见”的示例,说 def __init__(self, *args, a, b, c, **kwargs): 不起作用,但只要您使用的是 Python 版本,它就可以正常工作完全支持仅关键字参数。如果您仍在使用 Python 2,则根本无法使用仅关键字参数,但在 Python 3 上,“显而易见的”可以正常工作,如我的回答所示。

标签: python arguments keyword-argument pep-3102


【解决方案1】:

不提供默认值,关键字参数是必需的:

class ClassB(ClassA):
    def __init__(self, *args, a, b, c, **kwargs):
        super().__init__(*args, **kwargs)  # No need to pass arguments to super in Py3
        self.a = a
        self.b = b
        self.c = c

它们仍然必须是仅关键字,因为它们位于 *args 参数之后。

此功能与 PEP 3102 中的仅关键字参数同时添加,其中指出:

仅关键字参数不需要具有默认值。由于 Python 要求所有参数都绑定到一个值,并且由于将值绑定到仅关键字参数的唯一方法是通过关键字,因此此类参数是“必需的关键字”参数。此类参数必须由调用者提供,并且必须通过关键字提供。

需要明确的是,仅关键字参数(必需或默认)是 Python 3 独有的功能。如果您尝试在 Python 2 上执行此操作,则不可能让 Python 为您完成工作,您只需要自己执行检查即可。移至 Python 3; Python 2 将在 2019 年底结束生命周期(没有补丁,甚至出于安全考虑),因此无论如何新代码都应该以 Python 3 为目标。

仅作记录,您在 Python 2 上使用的代码会很糟糕,例如:

class ClassB(ClassA):
    def __init__(self, *args, **kwargs):
        try:
            self.a = kwargs.pop('a')
            self.b = kwargs.pop('b')
            self.c = kwargs.pop('c')
        except KeyError as e:
            # Convert to TypeError to match Python 3 behavior
            raise TypeError("__init__ missing required keyword-only argument: {!s}".format(e))
        super(ClassB, self).__init__(*args, **kwargs)

缺点是它不会出现在初始化程序/类签名中,并且手动弹出这样的参数更昂贵(在编写的代码和运行时)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2021-08-29
    • 2023-03-10
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    相关资源
    最近更新 更多