[如何让python类型在期望子类成为父类时将其识别为有效类型?

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

这里是我需要做的最小示例:

from typing import Callable, Any


class Data:
    pass


class SpecificData(Data):
    pass


class Event:
    pass


class SpecificEvent(Event):
    pass


def detect_specific_event(data: SpecificData, other_info: str) -> SpecificEvent:
    return SpecificEvent()


def run_detection(callback: Callable[[Data, Any], Event]) -> None:
    return


run_detection(detect_specific_event)

现在我收到警告:

Expected type '(Data, Any) -> Event', got '(data: SpecificData, other_info: str) -> SpecificEvent' instead 

在我看来,此警告似乎没有任何意义,因为SpecificData和SpecificEvent分别是Data和Event的子类型,所以一切都应该没问题。有没有一种方法可以像我期望的那样工作?我的想法是能够拥有类似的东西:

class OtherSpecificData(Data):
    pass


class OtherSpecificEvent(Event):
    pass


def detect_other_event(data: OtherSpecificData, other_info: str) -> OtherSpecificEvent:
    return OtherSpecificEvent()

run_detection(detect_other_event)

所以run_detection功能尽可能通用。现在,它发出与上述相同的警告。

python class typing callable subtype
2个回答
1
投票
参数子类型与返回子类型相反。

    返回值是从被叫方分配给主叫方的。
  • 参数值从呼叫者分配给被呼叫者。
  • 并且赋值应该比变量的期望类型更具体。例如:

    data: Data = SpecificData() # okay data: SpecificData = Data() # not okay

    所以您应该这样做:

    from typing import Callable, Any class Data: pass class SpecificData(Data): pass class Event: pass class SpecificEvent(Event): pass def detect_specific_event(data: Data, other_info: str) -> SpecificEvent: return SpecificEvent() def run_detection(callback: Callable[[SpecificData, Any], Event]) -> None: return run_detection(detect_specific_event)


  • 0
    投票
    花了我一段时间来记住要使用哪种打字方式,但是恕我直言,您想使用cast

    与其他语言中的用法不同,

    cast(x,y)不会do,但是它确实告诉您键入将y视为类型x。

    New in version 3.5.2. typing.cast(typ, val) Cast a value to a type. This returns the value unchanged. To the type checker this signals that the return value has the designated type, but at runtime we intentionally don’t check anything (we want this to be as fast as possible).
    就像编译语言一样,如果我读了它,我会特别注意代码:这真的可以在运行时工作吗?数据类型实际上是正确的吗?

    from typing import Callable, Any, cast class Data: pass class SpecificData(Data): pass class Event: pass class SpecificEvent(Event): pass def detect_specific_event(data: SpecificData, other_info: str) -> SpecificEvent: return SpecificEvent() def run_detection(callback: Callable[[Data, Any], Event]) -> None: return run_detection(cast((Callable[[Data, Any], Event]),detect_specific_event))

    [在这里,您基本上告诉打字,“接受我的话”,detect_specific_eventCallable[[Data, Any], Event])

    运行和类型检查的输出:

    $ mypy test2.py Success: no issues found in 1 source file $ python test2.py (venv)$ 😃 well your code says nothing.

    将sig更改为(💣确实不在那儿):

    run_detection(cast((Callable[[Data, Any], 💣int💣]),detect_specific_event))

    (venv) [email protected]$ mypy test2.py test2.py:28: error: Argument 1 to "run_detection" has incompatible type "Callable[[Data, Any], int]"; expected "Callable[[Data, Any], Event]" Found 1 error in 1 file (checked 1 source file) $ python test2.py $😃 well your code says nothing.

    © www.soinside.com 2019 - 2024. All rights reserved.