【问题标题】:Type-checking issue with io.TextIOBase in a UnionUnion 中 io.TextIOBase 的类型检查问题
【发布时间】:2020-07-14 22:26:06
【问题描述】:

在下面的代码中,我有一个函数可以接受一个字符串或一些TextIOBase。如果传递了字符串,则将其解释为应打开和读取的文件的路径。如果传递了TextIOBase,则将读取该流的内容:

from typing import Union
import io

def function(foo: Union[str, io.TextIOBase]) -> None:
    if isinstance(foo, str):
        foo = open(foo, "w")

这看起来应该没问题,因为联合应该是协变的,这意味着联合中一种类型的子类应该满足类型注释,在这种情况下,open() 的输出类型是TextIOBase 的子类。然而,mypy 抱怨:

union.py:6: error: Incompatible types in assignment (expression has type "TextIO", variable has type "Union[str, TextIOBase]")
Found 1 error in 1 file (checked 1 source file)

根据传递的参数,我认为open() 的返回类型可能存在歧义,因此我尝试改为创建StringIO,但得到了同样的错误。有什么想法吗?为什么mypy生我的气?

我也尝试过一些玩具类(例如Union[str, T1],然后分配T2,其中T2 是 T1 的子类),mypy 对此非常满意。

【问题讨论】:

    标签: python mypy


    【解决方案1】:

    typing 模块有一个专用对象:typing.TextIOopen 的返回类型基于 mode 参数确定,并评估为以下类型之一:TextIOBinaryIO

    【讨论】:

    • 成功了。我想知道 mypy 消息中的 TextIO 是什么。不过,类型检查对诚实至善的课程本身不起作用似乎仍然很奇怪。为什么需要typing 中的TextIOtyping 的文档没有提供太多的上下文。
    • @youngmit 我猜这是因为open 的返回类型取决于它的参数,所以你不能总是确定返回类型是什么并且需要某种回退(typing.IO)。想象一下open('test', mode=input()); mypy 将类型推断为IO。因此,为了实现与TextIOBinaryIO 的子类关系,所有内容都在typing 中定义。
    猜你喜欢
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-28
    相关资源
    最近更新 更多