【问题标题】:Typing: changing type of fieldin inherited class in python打字:在python中更改继承类中的字段类型
【发布时间】:2021-07-22 16:34:23
【问题描述】:

让我们来:

class A:
    pass

class A2(A):
    @property
    def f(self):
        return None

class B:
    def __init__(el: A)
        self._a = el

class B2(B):
    def __init__(el: A2)
        super().__init__(el)

    def m():
        self._a.f()

我现在在调用self._a.f() 时在最后一行出现打字错误,说“无法访问类型 A 的成员 f”,即使它是在 B 中的 A2 处声明的,并且它具有该成员。 声明此 sn-p 以使打字工作的正确方法是什么?

【问题讨论】:

  • 您在第一行 class A 之后忘记了 :
  • 为什么在 A 中将 f() 定义为 @property 而在 B2 中它是一个函数?这真是令人困惑
  • 我将更新代码以消除混淆。 F 只是一个占位符名称
  • 因为self._a被推断为A的实例

标签: python type-hinting python-typing


【解决方案1】:

A 没有成员f,因此尝试访问_a.f,其中_a: A 是错误的。要实现您想要的,您应该将f 定义为A 上的未实现函数,其子类应实现:

class A:
    @property
    def f(self):
        raise NotImplementedError

或使用抽象方法将其设为abstract base class

from abc import ABC, abstractmethod

class A(ABC):
    @property
    @abstractmethod
    def f(self): ...

这将通知类型检查器A 及其所有子类都有一个成员f,并且您的代码应该正确地进行类型检查。

如果你只想缩小B2._a的类型,这应该足够了:

class B2(B):
    _a: A2

    # rest of class definition
    ...

【讨论】:

  • 谢谢!这是唯一的选择吗?如果我不想扩展 A 的接口,因为除了 B2 之外没有其他类需要 m 方法怎么办?
  • 考虑通过在类主体中添加_a: A2(而不是在方法中!)显式注释B2._a 的类型。这足以在我的机器上进行代码类型检查(mypy 0.812)。我已经编辑了答案以包含代码。
猜你喜欢
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2020-05-07
  • 2012-03-25
相关资源
最近更新 更多