我对Python类型提示和mypy比较陌生,不知道为什么下面的代码无法通过mypy验证。
from typing import Callable, Union
class A:
a: int = 1
class B:
b: int = 1
def foo(cb: Union[Callable[[A], None], Callable[[B], None]]):
a = A()
cb(a)
def bar(a: A) -> None:
print(a)
foo(bar)
此操作失败,并显示以下消息
test.py:11: error: Argument 1 has incompatible type "A"; expected "B"
Found 1 error in 1 file (checked 1 source file)
从阅读这篇文章,我认为论点cb
可以采取Callable[[A], None]
或Callable[[B], None]
,但似乎情况并非如此?有人能解释一下这是怎么回事吗?这是我的事情和实现的怪癖,是我的假设错了还是这在某种程度上是预期的?
谢谢!
foo
只知道你告诉它的cb
:要么是一个以A
值为参数的函数,要么是一个以B
值为参数的函数。不是一个可以接受A
或B
的函数。
尽管是类型化的,但您根本不能真正调用cb
,因为您不知道它接受什么类型。(你知道它是两个中的一个,但不知道哪个是一个。)
更新:准确地说,正如@joel指出的,你不能用的值来调用它,只有是A
的实例或B
的实例。可以用一个both的实例来调用它。例如,下面的类型检查
class C(A, B):
pass
def foo(cb: Union[Callable[[A], None], Callable[[B], None]]):
c = C()
cb(c)
因为c
满足两个条件。