如何使python类型在期望其父类时将子类识别为有效类型



下面是我需要做的一个最小的例子:

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)

因此CCD_ 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)

我花了一段时间才记住要使用哪种类型,但IMHO你想使用cast

与其他语言中的使用不同,cast(x,y(不会执行任何操作,但它确实告诉键入将y视为类型x。运行时,这是一个无操作,只返回y.

就像编译过的语言一样,如果我阅读它,我会特别注意代码:这真的能在运行时工作吗?数据类型真的是正确的吗

  • 如果您不能保证以后生成数据的东西只会分发SpecificDatas,则带有LSP注释的重复闭包是合适的。如果可以,则可以进行强制转换。您的最小示例缺少该位,但如果您已经显示了通过print(data)的实际数据,那么我们就知道是否应用了LSP
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_event就是Callable[[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[[SpecificData, Any], SpecificEvent]),detect_specific_event))

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

相关内容

  • 没有找到相关文章

最新更新