键入文件或类文件对象的提示?

Mar*_*ery 57 python type-hinting

是否有任何正确的类型提示用于Python中的文件或类文件对象?例如,我如何键入提示此函数的返回值?

def foo():
    return open('bar')
Run Code Online (Sandbox Code Playgroud)

Way*_*ner 73

对于分别以文本模式或二进制模式打开的文件,请使用typing.TextIOtyping.BinaryIO类型.

来自文档:

typing.io

I/O流类型的包装器命名空间.

这定义了泛型类型IO[AnyStr]和别名TextIO,BinaryIO分别用于IO[str]IO[bytes].这些表示I/O流的类型,例如返回的open().

  • 该文档有点令人困惑,它表明了一个弃用,但我不完全确定它涵盖了什么,乐观的解释是它仅与typing.io命名空间有关,但我不热衷于在编程时过于乐观。 (3认同)
  • 这些似乎都不适合我:`def f() - > IO:return open('test')`给出"预期类型'IO',在PyCharm中得到'TextIOWrapper [str]'". (2认同)
  • @Tshirtman 我认为你可以对此持乐观态度。我发现 [this](https://bugs.python.org/issue42001) 与弃用有关的问题,并且似乎更清楚的是 `typing.io` 是要弃用的命名空间,因为 `typing.io.BinaryIO` 和其他也存在并且大多直接从`typing` 命名空间使用,例如`typing.BinaryIO`。 (2认同)

Cha*_*iam 24

简短的回答:

  • 你需要明确。那from typing import TextIO不仅仅是from typing import *.
  • 使用IO意味着文件没有指定什么样的
  • 使用TextIOBinaryIO如果您知道类型
  • 您当前无法指定它是为写入而打开或其编码。

举个例子:

from typing import BinaryIO

def binf(inf: BinaryIO):
    pass

with open('x') as f:
    binf(f)
Run Code Online (Sandbox Code Playgroud)

给出了一个检查错误(在 PyCharm 中) Expected type 'BinaryIO', got 'TextIO' instead


Max*_*xpm 7

如果您要注释参数的类型,请考虑使用typing.IOtyping.TextIOtyping.BinaryIO

它们可能会对调用者造成过度限制,因为它们包含您通常并不真正需要的内容,例如.encoding.newlines

相反,请考虑定义您自己的typing.Protocol. 这让您只需要您实际需要的“类似文件”界面的部分。

因此,例如,不要这样做:

def foo(file_like: typing.TextIO) -> None:
    read_str = file_like.read()
    # ...
Run Code Online (Sandbox Code Playgroud)

考虑这样做:

class TextFileLike(typing.Protocol):
    def read() -> str:
        ...

def foo(file_like: TextFileLike) -> None:
    read_str = file_like.read()
    # ...
Run Code Online (Sandbox Code Playgroud)

一些 Python 核心开发人员在https://github.com/python/typing/discussions/829上提供了此建议。

这些 [ typing.IOtyping.TextIOtyping.BinaryIO] 类旨在模拟“文件对象”的概念,但是当您开始了解“文件对象”在 Python 库系统中的实际使用方式时,您很快就会意识到,其中存在大量变化您到底可以用它们做什么。

此策略的缺点typing.Protocol是它限制了您以后更改实施的能力。例如,如果您稍后决定要调用.readline()而不是.read(),并且您没有将其包含.readline()在原始 中typing.Protocol,则需要对界面进行重大更改。换句话说,这是一个权衡,要么预先对调用者限制过多而导致 API 可用性问题,要么接口与实现耦合得太紧而导致破坏性更改。