在python 3.6中输入提示生成器

Jin*_*hoi 24 python pycharm python-3.x

根据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)
Run Code Online (Sandbox Code Playgroud)

但是,列表推导在PyCharm中给出以下错误.

Expected 'collections.Iterable', got 'Generator[int, None, None]' instead less... (?F1)
Run Code Online (Sandbox Code Playgroud)

知道为什么PyCharm将此视为错误吗?谢谢.


阅读一些答案后的一些澄清.我正在使用PyCharm Community Edition 2016.3.2(最新版本)并导入了typing.Generator(在代码中更新).上面的代码运行得很好,但PyCharm认为这是一个错误:

在此输入图像描述

所以,我想知道这实际上是PyCharm中的错误还是不支持的功能.

nev*_*ves 136

这不是问题的直接答案,但我认为这是一个更好的解决方案。

我使用下面的类型规范,Iterator[int]而不是生成器。验证没问题。我想这已经清楚多了。它更好地描述了代码意图,是Python 文档推荐的。

from typing import Iterator

def generate() -> Iterator[int]:
    for i in range(10):
        yield i
Run Code Online (Sandbox Code Playgroud)

如果您将生成器更改为列表或其他可迭代对象,它还允许将来进行重构。

我使用 Visual Studio Code 和 PyLance 进行输入验证。PyCharm mypy 应该具有相同的行为。

如果您使用的是Python 3.10 或更高版本,请将上面的导入命令更改为:

from collections.abc import Iterator
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么这被否决了。python 文档本身指出,可以使用“Iterator[YieldType]”或“Iterable[YieldType]”作为生成器,仅生成。请参阅https://docs.python.org/3.6/library/typing.html#typing.Generator (28认同)
  • `from collections.abc import Iterator` 是新的更好的方法。请参阅https://docs.python.org/3.10/library/typing.html#typing.Iterable (18认同)

小智 21

您需要导入该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
Run Code Online (Sandbox Code Playgroud)

以上将有所需的结果:

l = [i for i in generate()]
Run Code Online (Sandbox Code Playgroud)

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


正如评论中指出的那样,您可能不会使用最新版本的PyCharm.尝试切换到2016.3.2版本,你可能没问题.不幸的是,根据@AshwiniChaudhary的评论,这是一个众所周知的错误.

更多,报道的问题(最新版本的PyCharm)于去年12月提交.他们可能修复了它并将修改推送到同一版本.

  • 什么是“发送类型”? (14认同)
  • 这难道不会导致 OP 的 `Generator` 出现 `NameError` 吗? (2认同)

Mar*_*ski 11

、和在细节上略有不同,并且Iterator携带不同类型的信息,因此了解差异可能有助于为您的代码选择正确的信息:GeneratorIterable

  • Iterable是这三个术语中最通用的术语,表示任何可以迭代的对象。AnIterable必须有一个__iter__()返回迭代器的方法,或者一个__getitem__()具有从 开始的顺序索引的方法0

  • Iterator是 的子类型Iterable。AnIterator是一个实现迭代器协议的对象,其中包括__iter__()__next__()方法。该__iter__()方法应该返回迭代器对象本身,并且该__next__()方法应该返回迭代器的下一个值。

  • Generator是 的更专业的子类型Iterator。通过调用生成器函数来生成对象Generator,生成器函数是使用yield关键字定义的。该Generator类型是独一无二的,因为它有两个用于发送和返回类型的附加类型参数,允许更具表现力的类型提示,特别是当生成器用于类似协同例程的模式时。Iterator与和不同IterableGenerator类型可用于指定可发送到生成器或从生成器返回的值的类型,使用语法Generator[YieldType, SendType, ReturnType]

因此,如何输入提示主要取决于您的代码实际上在做什么:

  • Iterable当期望函数接受任何可迭代对象而不考虑迭代器的确切类型时使用。
  • Iterator当函数需要专门处理迭代器对象而不指定迭代器的确切子类型时使用。
  • 用于Generator显式指示函数返回/接受生成器对象,并可选择指定可发送到生成器或从生成器返回的值的类型。