[英]In python type-hinting, how can I make an argument accept any subclass of a base class?
[英]How can I get format to not cause a type-hinting error?
我在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退回我的错误? 如您所见,我尝试使用强制转换,但仍然失败。
这个问题看起来很相似,但是我的特殊情况很奇怪,因为Mypy看起来还不错,只要我不使用format
函数(不过,使用print
函数就可以了)。
我有什么办法可以避免格式行给我错误? (或者我应该只是# type: ignore
它们?)
编辑:请注意,这似乎不仅仅是我的Atom短绒棉的问题。 我正在使用Mypy版本0.701
并且在文件上运行Mypy,结果如下:
$ python3 -m mypy testing_list_iter.py --disallow-any-expr
testing_list_iter.py:7: error: Expression type contains "Any" (has type "List[Any]")
testing_list_iter.py:10: error: Expression type contains "Any" (has type "List[Any]")
这实际上与列表理解无关:实际上,这是str.format(...)
的类型签名, str.format(...)
如何执行类型推断以及--disallow-any-expr
标志之间的不良交互。
这是str.format(...)
的类型签名, 从typeshed中拉出 :
def format(self, *args: Any, **kwargs: Any) -> str: ...
当mypy对函数调用执行类型推断时,它将尝试使用声明的参数类型来帮助为您传入的表达式提供上下文。
因此,在这种情况下,由于此处的参数均为Any
,因此mypy将意识到它可以简化通常需要执行的许多类型推断。 因此,如果我们将任何列表文字传递给str.format(...)
,mypy只会决定“嘿,推断的类型可以只是List[Any]
”。
这是一个演示此行为的示例程序(通过--disallow-any-expr
标志进行检查时):
from typing import cast, Any
def test1(x: Any) -> None:
pass
def test2(x: object) -> None:
pass
# Revealed type is 'builtins.list[Any]'
# Expression type contains "Any" (has type "List[Any]")
test1(reveal_type([1, 2, 3, 4]))
# Revealed type is 'builtins.list[builtins.int*]'
test2(reveal_type([1, 2, 3, 4]))
请注意,当我们尝试使用接受object
而不是Any
的函数时,mypy将推断完整类型,而不是执行此快捷方式。 (从技术上讲,Mypy可以做同样的捷径,因为所有类型也都继承了object
,但是我怀疑这只是更简单的实现方式-不像Any
那样, object
只是一个普通的普通类型,因此与这有点奇怪。)
通常,mypy如何处理这种情况并不重要:无论哪种方式,您都能获得准确的结果。
但是,-- --disallow-any-expr
标志仍然很新,并且尚未经过测试(对于许多人来说,它太激进了,尤其是那些试图在现有代码库上使用mypy的人),因此我们有时会遇到这些不良的交互。时间。
那么,解决方法是什么?
最好的可能的修复将是你出力拉请求Typeshed修改str.format(...)
和unicode.format(...)
在builtins.pyi文件,以便他们接受的对象,而不是Any
。
无论如何,此更改都将符合Typeshed的贡献准则 -特别是在“公约”部分中间的以下代码段:
添加类型提示时,请尽可能避免使用
Any
类型。 在以下情况下保留Any
的使用:
- 当前类型系统中无法表达正确的类型; 和
- 以避免工会退货(见上文)。
请注意,如果要表示某个函数可以接受任何字面值,则
Any
不是正确的类型:在这种情况下,请使用object
。
然后,您等待mypy的下一个发行版,从理论上讲应该是很快的。
同时,您可以做的就是将列表理解的结果分配给一个新变量,然后将其传递给str.format(...)
:
results = [value for value in [1, 2, 3, 4]]
print("{}".format(results))
这将导致mypy在没有Any
上下文的情况下推断出列表理解的类型,从而导致其推断出完整的类型。 这--disallow-any-expr
与--disallow-any-expr
标志的不良交互。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.