What exactly are iterator, iterable, and iteration?

前端 未结 13 1643
遥遥无期
遥遥无期 2020-11-21 05:27

What is the most basic definition of \"iterable\", \"iterator\" and \"iteration\" in Python?

I have read multiple definitions but I am unable to identify the exact m

相关标签:
13条回答
  • 2020-11-21 06:10

    Here's my cheat sheet:

     sequence
      +
      |
      v
       def __getitem__(self, index: int):
      +    ...
      |    raise IndexError
      |
      |
      |              def __iter__(self):
      |             +     ...
      |             |     return <iterator>
      |             |
      |             |
      +--> or <-----+        def __next__(self):
           +        |       +    ...
           |        |       |    raise StopIteration
           v        |       |
        iterable    |       |
               +    |       |
               |    |       v
               |    +----> and +-------> iterator
               |                               ^
               v                               |
       iter(<iterable>) +----------------------+
                                               |
       def generator():                        |
      +    yield 1                             |
      |                 generator_expression +-+
      |                                        |
      +-> generator() +-> generator_iterator +-+
    

    Quiz: Do you see how...

    1. every iterator is an iterable?
    2. a container object's __iter__() method can be implemented as a generator?
    3. an iterable that has a __next__ method is not necessarily an iterator?

    Answers:

    1. Every iterator must have an __iter__ method. Having __iter__ is enough to be an iterable. Therefore every iterator is an iterable.
    2. When __iter__ is called it should return an iterator (return <iterator> in the diagram above). Calling a generator returns a generator iterator which is a type of iterator.

      class Iterable1:
          def __iter__(self):
              # a method (which is a function defined inside a class body)
              # calling iter() converts iterable (tuple) to iterator
              return iter((1,2,3))
      
      class Iterable2:
          def __iter__(self):
              # a generator
              for i in (1, 2, 3):
                  yield i
      
      class Iterable3:
          def __iter__(self):
              # with PEP 380 syntax
              yield from (1, 2, 3)
      
      # passes
      assert list(Iterable1()) == list(Iterable2()) == list(Iterable3()) == [1, 2, 3]
      
    3. Here is an example:

      class MyIterable:
      
          def __init__(self):
              self.n = 0
      
          def __getitem__(self, index: int):
              return (1, 2, 3)[index]
      
          def __next__(self):
              n = self.n = self.n + 1
              if n > 3:
                  raise StopIteration
              return n
      
      # if you can iter it without raising a TypeError, then it's an iterable.
      iter(MyIterable())
      
      # but obviously `MyIterable()` is not an iterator since it does not have
      # an `__iter__` method.
      from collections.abc import Iterator
      assert isinstance(MyIterable(), Iterator)  # AssertionError
      
    0 讨论(0)
提交回复
热议问题