Iterable[str] 不是 str 的 Python 类型提示

fla*_*gam 20 python types type-hinting

在Python中,有没有办法区分字符串和其他字符串的可迭代对象?

Astr作为Iterable[str]类型是有效的,但这可能不是函数的正确输入。例如,在这个简单的示例中,旨在对文件名序列进行操作:

from typing import Iterable

def operate_on_files(file_paths: Iterable[str]) -> None:
    for path in file_paths:
        ...
Run Code Online (Sandbox Code Playgroud)

传入单个文件名会产生错误的结果,但不会被类型检查捕获。我知道我可以在运行时检查字符串或字节类型,但我想知道是否可以使用类型检查工具捕获类似的愚蠢错误。

我查看了该collections.abc模块,似乎没有任何 abc 包含典型的可迭代对象(例如列表、元组)但排除字符串。同样,对于typing模块来说,似乎没有不包含字符串的迭代类型。

Bro*_*ark 10

截至 2022 年 3 月,答案是否定的

这个问题至少从 2016 年 7 月起就已经被讨论过。关于区分str和 的提议Iterable[str]Guido van Rossum写道:

因为str 一个有效的可迭代对象,所以str这是很棘手的。人们已经提出了各种建议,但它们并不容易适合类型系统。

您需要使用Union(3.10 之前的版本)或|(3.10 及更高版本)列出您希望函数显式接受的所有类型。

例如,对于 3.10 之前的版本,请使用:

from typing import Union
## Heading ##
def operate_on_files(file_paths: Union[TypeOneName, TypeTwoName, etc.]) -> None:
    for path in file_paths:
        ...
Run Code Online (Sandbox Code Playgroud)

对于 3.10 及更高版本,请使用:

## Heading ##
def operate_on_files(file_paths: TypeOneName | TypeTwoName | etc.) -> None:
    for path in file_paths:
        ...
Run Code Online (Sandbox Code Playgroud)

如果您碰巧使用 Pytype,它不会被视为str(正如Iterable[str]Kelly Bundy指出的那样)。但是,这种行为是特定于类型检查器的,并且在其他类型检查器中并未得到广泛支持。