与可呼叫的结合的Mypy类型混乱

发布于 2025-01-29 06:21:38 字数 678 浏览 3 评论 0原文

我对Python Type提示和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],无],但似乎并非如此?有人可以解释这里发生了什么吗?这是一件杂乱无章的事情,还是实现怪癖,我的假设是错误的,还是以某种方式期望的?

谢谢!

I'm relatively new to Python type hinting and mypy and was wondering why the following code fails mypy verification.

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)

This fails with the following message

test.py:11: error: Argument 1 has incompatible type "A"; expected "B"
Found 1 error in 1 file (checked 1 source file)

From reading this, I would assume that the argument cb can either take a Callable[[A], None] or a Callable[[B], None] but it seems that's not the case? Can someone explain what's going on here? Is this a mypy thing and an implementation quirk, are my assumptions wrong or is this somehow expected?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

复古式 2025-02-05 06:21:38

foo只知道您对cb>:要么是将a值作为参数的函数,要么是一个函数这将b值作为参数。它是不是可以使用ab的函数。

按原样输入,您无法真正调用CB,因为您不知道它接受了哪种类型。 (您知道这是两个,但不是一个


。 /em> a的实例或b的实例。您可以将其称为两个实例的值。例如,以下类型检查

class C(A, B):
    pass

def foo(cb: Union[Callable[[A], None], Callable[[B], None]]):
    c = C()
    cb(c)

是因为c满足任何一个条件。

foo only knows what you told it about cb: either it is a function that takes an A value as an argument, or it is a function that takes a B values as an argument. It is not a function that can take either an A or a B.

Typed as it is, you can't really call cb at all, because you don't know what type it accepts. (You know it's one of two, but not which one.)


Update: to be precise, as pointed out by @joel, you can't call it with a value that is only an instance of A or an instance of B. You could call it with a value that is an instance of both. For example, the following type checks

class C(A, B):
    pass

def foo(cb: Union[Callable[[A], None], Callable[[B], None]]):
    c = C()
    cb(c)

because c satisfies either condition.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文