我怎样才能使格式不引起输入错误?

2024-04-19 15:36:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我在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,结果如下:

^{2}$

Tags: theinformatforvalueontypeany
1条回答
网友
1楼 · 发布于 2024-04-19 15:36:35

这实际上与列表理解无关:这实际上是str.format(...)的类型签名、mypy执行类型推断的方式和 disallow-any-expr标志之间的不良交互。在

以下是str.format(...)pulled from typeshed的类型签名:

def format(self, *args: Any, **kwargs: Any) -> str: ...

当您试图在mypy函数中对声明的类型调用myll时,请尝试在该类型上调用myll。在

所以在本例中,由于这里的参数都是Any,mypy将认识到它可以简化它通常需要做的许多类型推断。因此,如果我们将任何列表文本传入str.format(...),mypy将只决定“嘿,推断的类型可以是List[Any]”。在

下面是一个演示此行为的示例程序(使用 disallow-any-expr标志进行检查时):

^{pr2}$

请注意,当我们尝试使用接受object而不是Any的函数时,mypy将推断完整类型,而不是执行此快捷方式。(从技术上讲,Mypy可以实现同样的快捷方式,因为所有类型都是object的子类,但是我怀疑在实现方面更简单一些,不像Anyobject只是一个常规的普通旧类型,因此与它的特殊大小写交互有点奇怪。)

通常,mypy如何准确地处理这个问题并不重要:不管怎样,都可以得到准确的结果。在

但是, disallow-any-expr标志仍然很新,而且相对来说还没有经过测试(对于很多人来说,它太过激进了,特别是那些试图在现有的代码库上使用mypy的人),所以我们时不时会遇到这些不好的交互。在


那么,解决办法是什么?在

最好的解决方法是提供一个pull请求来修改builtins.pyi文件中的str.format(...)和{},这样它们接受对象而不是{}。在

此更改将与Typeshed的contribution guidelines一致,具体地说,这段代码位于“约定”部分的中间:

When adding type hints, avoid using the Any type when possible. Reserve the use of Any for when:

  • the correct type cannot be expressed in the current type system; and
  • to avoid Union returns (see above).

Note that Any is not the correct type to use if you want to indicate that some function can accept literally anything: in those cases use object instead.

然后,等待mypy的下一个版本,理论上应该很快就会发布。在

同时,您可以做的只是将列表理解的结果分配给一个新变量,然后将那个传递到str.format(...)

results = [value for value in [1, 2, 3, 4]]
print("{}".format(results))

这将导致mypy在没有Any上下文的情况下推断列表理解的类型,从而推断出完整的类型。这避免了与 disallow-any-expr标志的不良交互。在

相关问题 更多 >