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

问题描述 投票:0回答:3

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

A

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

from typing import Iterable

def operate_on_files(file_paths: Iterable[str]) -> None:
    for path in file_paths:
        ...

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

我查看了

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

python types type-hinting
3个回答
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: ...
对于 3.10 及更高版本,请使用:

## Heading ## def operate_on_files(file_paths: TypeOneName | TypeTwoName | etc.) -> None: for path in file_paths: ...
如果您碰巧使用 Pytype,

它不会将 str

 视为 
Iterable[str]
(正如 
Kelly Bundy 所指出的)。但是,这种行为是特定于类型检查器的,并且在其他类型检查器中并未得到广泛支持。


0
投票

pytype

(来自 Google 的类型检查器)默认将 
str
 视为不可迭代,如果将 
str
 传递给需要 
Iterable[str]
 的函数,则会引发错误。如果您确实需要将 
str
 处理为 
Iterable[str]
,则必须通过 
iter(s)

参见

https://google.github.io/pytype/faq.html#why-doesnt-str-match-against-string-iterables


0
投票
在某些情况下,如果您使用 Mypy

实际上有一种方法:使用

@overload

Never
 作为返回类型。

from typing import overload, Never from collections.abc import Iterable # Or Sequence @overload def first(v: str) -> Never: ... @overload def first(v: Iterable[str]) -> str: ... def first(v: Iterable[str]) -> str: return next(iter(v))
但这还不够。 Mypy 仍然会

认为以下内容没问题

first(['foo']) # Fine first('foo') # Anything after this line is simply ignored. a = 'bar' reveal_type(a) # Silently emit nothing.
 

--warn-unreachable

 标志允许您配置此行为。有了它,Mypy 
将引发错误,表示该行无法访问:

first(['foo']) # Fine first('foo') # Still no error, however. a = 'bar' # error: Statement is unreachable
另一方面,虽然没有引发任何错误,但在幕后使用 Pyright 的 Pylance 会淡出无法访问的代码:

它只对显式类型提示的代码这样做:

© www.soinside.com 2019 - 2024. All rights reserved.