【问题标题】:How do I properly annotate cooperative inherance in Python?如何在 Python 中正确注释协作继承?
【发布时间】:2020-05-04 08:18:12
【问题描述】:

假设我有这样的事情:

from typing import Mapping, Any


class Hidden:

    def __init__(self, z: float, **kwargs: Any):
        super().__init__(**kwargs)
        self.z = z


class Base:

    def __init__(self, x: int, **kwargs: Any):
        super().__init__(**kwargs)
        self.x = x


class Inherited(Base):

    def __init__(self, y: int, **kwargs: Any):
        super().__init__(**kwargs)
        self.y = y


class Final(Inherited, Hidden):
    pass

我应该如何注释它?我尝试用TypedDict 的一些用法替换Any,但它只需要值类型。这是我能做到的最好的吗?

【问题讨论】:

    标签: python mypy python-typing


    【解决方案1】:

    更新
    由于Inherited 需要xy 来初始化,它们应该被显式定义为参数。 kwargs 用于协作继承,以允许一个类调用另一个类的 init,而无需明确担心参数的类型(此处为 z:float)。因此 Any 在这种情况下确实是正确的注释。

    同样,为了初始化Final,我建议使用所有必需的参数定义__init__,即def __init__(self, x:int, y:int, z:float, **kwargs:Any)

    同样,Final 也可以被其他类继承,它不关心派生类的参数,但保留**kwargs:Any 以实现协作继承兼容性

    ps,很抱歉绕着同一件事转来转去。

    旧答案
    python 中的 kwargs 是键值对的字典,这些键值对不在该方法的显式定义参数中。因此,**kwargs 最终会收集任何 foo=bar 参数,其中 foo 不在定义的参数中。
    bar 的值几乎可以是任何值,这就是为什么使用 Any 的原因,因为 ** 表示这些值将被自然包裹在 kwargs 字典中。
    不过,您可以在此处注释值的类型 bar
    **kwargs:int 意味着您可以传递任何未声明的键值对,只要它是一个 int。

    【讨论】:

    • 同样继承不知道隐藏。所以工会还不够好。
    • 我同意你对问题的描述
    • 既然 x, y, z 是初始化 Final 所必需的,难道不应该明确定义吗?
    • 问题是你不了解z,所以无论你在Final中做什么,你都不能在Inherited中明确定义它。
    • 我认为在每个类中使用 Any 确实是正确的方法,因为每个类只关心它自己的 x/y/z,因此独立于其他类。对于 Inherited,我会明确定义 x:int, y:int,因为这是它初始化的必要条件。就我个人而言,我将 kwargs 用于很少使用的可选参数而不是必要的参数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2011-05-03
    相关资源
    最近更新 更多