我在Python中列出了以下理解:
from typing import cast
# everything is fine
print([value for value in [1, 2, 3, 4]])
# on the first "value": Expression type contains "Any" (has type "List[Any]")
print("{}".format([value for value in [1, 2, 3, 4]]))
# on the "cast": Expression type contains "Any" (has type "List[Any]")
print("{}".format([cast(int, value) for value in [1, 2, 3, 4]]))
为什么使用format
会导致Mypy返回错误?如你所见,我试着使用铸造,但还是失败了。在
This question看起来很相似,但我的特殊情况很奇怪,因为只要我不使用format
函数,Mypy似乎就没问题(但是print
函数总是可以的)。在
有什么我可以做的,以避免有格式的行给我错误?(或者我应该只是# type: ignore
他们?)在
编辑:
请注意,这似乎不仅仅是我的Atom linter的问题。
我使用的是Mypy版本0.701
,我对该文件运行Mypy,结果如下:
这实际上与列表理解无关:这实际上是
str.format(...)
的类型签名、mypy执行类型推断的方式和disallow-any-expr
标志之间的不良交互。在以下是
str.format(...)
,pulled from typeshed的类型签名:当您试图在mypy函数中对声明的类型调用myll时,请尝试在该类型上调用myll。在
所以在本例中,由于这里的参数都是
Any
,mypy将认识到它可以简化它通常需要做的许多类型推断。因此,如果我们将任何列表文本传入str.format(...)
,mypy将只决定“嘿,推断的类型可以是List[Any]
”。在下面是一个演示此行为的示例程序(使用
^{pr2}$disallow-any-expr
标志进行检查时):请注意,当我们尝试使用接受
object
而不是Any
的函数时,mypy将推断完整类型,而不是执行此快捷方式。(从技术上讲,Mypy可以实现同样的快捷方式,因为所有类型都是object
的子类,但是我怀疑在实现方面更简单一些,不像Any
,object
只是一个常规的普通旧类型,因此与它的特殊大小写交互有点奇怪。)通常,mypy如何准确地处理这个问题并不重要:不管怎样,都可以得到准确的结果。在
但是,
disallow-any-expr
标志仍然很新,而且相对来说还没有经过测试(对于很多人来说,它太过激进了,特别是那些试图在现有的代码库上使用mypy的人),所以我们时不时会遇到这些不好的交互。在那么,解决办法是什么?在
最好的解决方法是提供一个pull请求来修改builtins.pyi文件中的},这样它们接受对象而不是{}。在
str.format(...)
和{此更改将与Typeshed的contribution guidelines一致,具体地说,这段代码位于“约定”部分的中间:
然后,等待mypy的下一个版本,理论上应该很快就会发布。在
同时,您可以做的只是将列表理解的结果分配给一个新变量,然后将那个传递到
str.format(...)
:这将导致mypy在没有
Any
上下文的情况下推断列表理解的类型,从而推断出完整的类型。这避免了与disallow-any-expr
标志的不良交互。在相关问题 更多 >
编程相关推荐