【问题标题】:What's the difference between Mypy iterators and generators?Mypy 迭代器和生成器有什么区别?
【发布时间】:2019-10-25 22:36:45
【问题描述】:

主要区别是什么?分别应该使用什么以及在哪里使用?

例如,在这个例子中使用 - 和 Iterator 和 Generator 对我来说似乎很合适......但它是真的吗?

迭代器

from typing import Generator, Iterator

def fib(n: int) -> Iterator[int]:
    a :int = 0
    b :int = 1
    while a < n:
        yield a
        a, b = b, a+b

print([x for x in fib(3)])

生成器

from typing import Generator 

def fib(n: int) -> Generator[int, None, None]:
    a :int = 0
    b :int = 1
    while a < n:
        yield a
        a, b = b, a+b

print([x for x in fib(3)])

【问题讨论】:

标签: python-3.x types mypy


【解决方案1】:

当您不确定某些内置类型到底是什么时,我建议您查看Typeshed,这是 Python 标准库(以及一些选择的第 3 方模块)的类型提示存储库。 Mypy 在每个版本中都包含一个 typeshed 版本。

例如,here are the definitions 究竟是什么迭代器和生成器:

@runtime
class Iterator(Iterable[_T_co], Protocol[_T_co]):
    @abstractmethod
    def __next__(self) -> _T_co: ...
    def __iter__(self) -> Iterator[_T_co]: ...

class Generator(Iterator[_T_co], Generic[_T_co, _T_contra, _V_co]):
    @abstractmethod
    def __next__(self) -> _T_co: ...

    @abstractmethod
    def send(self, value: _T_contra) -> _T_co: ...

    @abstractmethod
    def throw(self, typ: Type[BaseException], val: Optional[BaseException] = ...,
              tb: Optional[TracebackType] = ...) -> _T_co: ...

    @abstractmethod
    def close(self) -> None: ...

    @abstractmethod
    def __iter__(self) -> Generator[_T_co, _T_contra, _V_co]: ...

    @property
    def gi_code(self) -> CodeType: ...
    @property
    def gi_frame(self) -> FrameType: ...
    @property
    def gi_running(self) -> bool: ...
    @property
    def gi_yieldfrom(self) -> Optional[Generator]: ...

注意:

  1. 迭代器只有两种方法:__next__ 和 __iter__,但生成器有更多。
  2. 生成器是迭代器的子类型——每个生成器也是迭代器,但反之则不然。

但这在高层次上意味着什么?

嗯,简而言之,使用迭代器,信息流是单向的。当你有一个迭代器时,你能做的就是调用__next__ 方法来获取下一个要产生的值。

相比之下,生成器的信息流是双向:您可以通过send 方法将信息返回发送到生成器。

实际上,这就是其他两个类型参数的用途——当您执行Generator[A, B, C] 时,您声明您生成的值是A 类型,您发送到生成器的值是@ 类型987654334@,您从生成器返回的值的类型为C。

这里还有一些有用的阅读材料:

  1. python generator "send" function purpose?
  2. Difference between Python's Generators and Iterators
  3. Return in generator together with yield in Python 3.3
  4. https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

那么,什么时候应该使用迭代器和生成器?

嗯,一般来说,您应该偏向于使用有助于调用者了解您期望如何使用返回值的类型。

例如,以您的fib 为例。你所做的只是产生值:信息流是单向的,代码并没有真正设置为接受来自调用者的信息。

因此,在这种情况下使用 Iterator 而不是 Generator 是最容易理解的:Iterator 最能反映 fib 实现的单向性。

(如果您编写了一个数据流是双向的生成器,那么您当然需要使用生成器而不是迭代器。)

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 2021-04-26
    • 2014-12-05
    • 1970-01-01
    • 2012-06-14
    • 2011-07-17
    • 2012-02-10
    • 2013-06-17
    • 2011-08-26
    相关资源
    最近更新 更多