如何在python中继承类型提示?

问题描述 投票:5回答:2

所以我的问题是,当我有一个类A的类来做事情并且我将这些函数用作子类(B)时,它们仍然为类A键入,并且不接受我的类B对象作为参数或函数签名。

我的问题简化了:

from typing import TypeVar, Generic, Callable

T = TypeVar('T')


class Signal(Generic[T]):
    def connect(self, connector: Callable[[T], None]) -> None:
        pass

    def emit(self, payload: T):
        pass


class A:
    def __init__(self) -> None:
        self.signal = Signal[A]()

    def do(self) -> None:
        self.signal.emit(self)

def handle_b(b: "B") -> None:
    print(b.something)

class B(A):
    def __init__(self) -> None:
        super().__init__()
        self.signal.connect(handle_b)

    @property
    def something(self) -> int:
        return 42

我也可以提供完整的信号类,但这会分散注意力。这让我在mypy中出现一个错误 - >错误:“信号”的参数1与“连接”具有不兼容的类型Callable [[B],None];预期可调用[[A],无]

由于信号处理是在A中实现的,因此子类B不能指望返回B类型的对象,即使它显然应该很好......

python inheritance python-3.5 type-hinting mypy
2个回答
0
投票

类型提示错误完全正确。你在SignalA方法中用__init__作为类型创建了一个A实例:

self.signal = Signal[A]()

传递子类很好,但所有与Signal实例交互的代码现在只能用于A实例。另一方面,handle_b()需要B的一个实例,而不能降低对A的要求。

删除约束:

self.signal = Signal()

或者使用正确的类型在每个子类中创建一个实例。


0
投票
from __future__ import annotations
from typing import TypeVar, Generic, Callable

T = TypeVar('T')


class Signal(Generic[T]):
    def connect(self, connector: Callable[[T], None]) -> None:
        pass

    def emit(self, payload: T):
        pass


class A(Generic[T]):
    def __init__(self) -> None:
        self.signal = Signal[T]()

    def do(self: A) -> None:
        self.signal.emit(self)


def handle_b(b: B) -> None:
    print(b.something)


class C:
    pass


def handle_c(c: C) -> None:
    print(c)


class B(A[B]):
    def __init__(self) -> None:
        super().__init__()
        self.signal.connect(handle_b)  # OK
        self.signal.connect(handle_c)  # incompatible type

    @property
    def something(self) -> int:
        return 42
© www.soinside.com 2019 - 2024. All rights reserved.