根据 PEP-484,我们应该能够键入提示生成器函数,如下所示:
from typing import Generator
def generate() -> Generator[int, None, None]:
for i in range(10):
yield i
for i in generate():
print(i)
但是,列表理解在 PyCharm 中给出以下错误。
预期的“collections.Iterable”,得到“Generator[int,None,None]”而不是更少...(⌘F1)
知道为什么 PyCharm 认为这是错误吗?
阅读一些答案后进行一些澄清。我使用的是PyCharm Community Edition 2016.3.2(最新版本)并已导入
typing.Generator
(在代码中更新)。上面的代码运行得很好,但 PyCharm 认为这是一个错误:
所以,我想知道这实际上是一个错误还是 PyCharm 中不受支持的功能。
您需要导入
typing
模块。根据文档:
生成器函数的返回类型可以用泛型注释 类型
提供者Generator[yield_type, send_type, return_type]
模块typing.py
试试这个方法:
from typing import Generator
def generate() -> Generator[int, None, None]:
for i in range(10):
yield i
以上就会得到想要的结果:
l = [i for i in generate()]
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
正如评论中所指出的,您可能不会使用 PyCharm 的最新版本。尝试切换到版本2016.3.2,你可能会没事。不幸的是,根据 @AshwiniChaudhary 评论,这是一个众所周知的错误。
此外,报告的问题(针对 PyCharm 的最后一个版本)是于去年 12 月提交的。他们可能修复了它并将修改推送到同一版本中。
这不是问题的直接答案,但我认为这是一个更好的解决方案。
我正在使用下面的类型规范,使用
Iterator[int]
而不是 Generator。验证没问题。我想这已经清楚多了。它更好地描述了代码意图,并且受到Python 文档的推荐。
from typing import Iterator
def generate() -> Iterator[int]:
for i in range(10):
yield i
如果您将生成器更改为列表或其他可迭代对象,它还允许将来进行重构。
我使用 Visual Studio Code 和 PyLance 进行输入验证。 PyCharm mypy 应该具有相同的行为。
如果您使用的是Python 3.10或更高版本,请将上面的导入命令更改为:
from collections.abc import Iterator
Iterator
、Generator
和Iterable
在细节上略有不同,并且携带不同类型的信息,因此了解差异可能有助于为您的代码选择正确的:
Iterator
只是一个实现迭代器协议的对象(包括 __iter__()
和 __next__()
方法),
Generator
更具体,因为它不仅表示该函数返回 Iterator
,而且还表示它是使用生成器实现的(即使用 yield
表达式的函数)。生成器函数返回迭代器。
最后是
Iterable
,它比Iterator
更通用,因为Iterable
可以是任何可以迭代的对象,包括但不限于列表、元组和迭代器。可迭代对象必须具有返回迭代器的 __iter__()
方法,或具有从 __getitem__()
开始的顺序索引的 0
方法。
所以如何输入提示主要取决于你的代码真正在做什么:
Iterable
。Iterator
,而不指定迭代器的确切子类型。Generator
显式指示函数返回/接受生成器对象,并可选择指定可以发送到生成器或从生成器返回的值的类型。