我正在根据变量类型(其他类型的联合)在条件中定义功能。 Mypy在这种情况下注入了这种类型的范围,但似乎将这些知识丢弃了。
我不明白为什么。这是mypy中的错误吗?
考虑一下:
from typing import Union, Callable
def test(a: Union[None, Callable]):
if a is None:
pass
else:
def test0():
a()
def test1(b: str):
a(b)
callable_a = a
def test2(b: str):
callable_a(b)
a()
a('foo')
mypy的输出:
test.py:9: error: "None" not callable
Found 1 error in 1 file (checked 1 source file)
第9行是test1的主体。似乎在这里使用整个 union [none,collable]
是应用
(从这个示例中不清楚“整个联盟”,在实际代码中,它的联合[无,序列,可召唤]和没有序列的mypy对象是不可呼应的)。
外部功能定义,问题没有出现。
有些想法:
-
Callable_a
只能是一个可笑的人,因此我更愿意接受Mypy不会对此抱怨。我不明白为什么它在抱怨。
-
test0
和 test1
呼叫 a
,差异只是参数。为什么这会与Mypy有所不同,尤其是当 a
的签名不确定时?
如果有所不同,我正在运行MyPy 0.950。
I'm defining functions inside a condition based on a variables type, a Union of other types. mypy infers that the type is narrowed down in this context, but seems to throw this knowledge away.
I don't understand why. Is this a bug in mypy?
Consider this:
from typing import Union, Callable
def test(a: Union[None, Callable]):
if a is None:
pass
else:
def test0():
a()
def test1(b: str):
a(b)
callable_a = a
def test2(b: str):
callable_a(b)
a()
a('foo')
mypy's output:
test.py:9: error: "None" not callable
Found 1 error in 1 file (checked 1 source file)
line 9 is the body of test1. Seems that here the whole Union[None, Callable]
is applied
("the whole union" is not clear from this example, in the actual code it's Union[None, Sequence, Callable] and mypy objects that both None and Sequence are not callable).
outside function definitions, the problem does not appear.
Some thoughts:
callable_a
can only ever be a callable, so I'm a bit more willing to accept that mypy doesn't complain about this. I don't understand why it's complaining anyway.
- both
test0
and test1
call a
, the difference is only the argument. Why does this make a difference to mypy, especially here when the signature of a
is undefined?
I'm running mypy 0.950 if it makes a difference.
发布评论
评论(1)
这是正确的行为,在 mypy 文档。
a
的推断由于较晚的绑定而言是错误的。这是文档中给出的示例:
现在关于您的代码:首先,未检查没有注释的功能,因此您不会看到所有实际错误。添加类型提示后,我们有以下内容:
现在只有
test2
是有效的,这是预期的(请参阅显示的类型)。callable_a
被推断为callable
none
键入pove,因此您不能分配none none < /code>稍后。您可以使用
callable(a)
内部test0
和test1
(肮脏的方式)解决此问题,或使用与test2
。默认参数绑定(使用def test0(a:callable = a)
也应该有效,但mypy
出于某种原因不喜欢它 - 它是误报,但是现在很难处理,或者现在没有时间浏览 /a>如果您对
mypy
对此的看法有兴趣C67CB3D56A8E4BB2A718E6B346E0E7BA“ rel =“ nofollow noreferrer”>一个游乐场可以在线玩这个。This is correct behavior which is well explained in the
mypy
docs. Inference ofa
would be simply wrong because of late binding.Here's the example given in the docs:
Now about your code: First, functions without annotations are not checked, so you don't see all real errors. After adding type hints, we have the following:
Now only
test2
is valid, which is expected (see revealed type).callable_a
is inferred to beCallable
only fromis None
type guard, so you cannot assignNone
to it later. You can fix this withassert callable(a)
insidetest0
andtest1
(dirty way) or use the same pattern as withtest2
. Default argument binding (usingdef test0(a: Callable = a)
should be valid too butmypy
doesn't like it for some reason - it is a false positive, but probably too hard to deal with or devs don't have time for it now.Look through this issue if you are interested in
mypy
's opinion on that. Here's a playground to play with this online.