Iterables in Python, and two iterators usage ITER () function Detailed

In Python, there are these two concepts confusing. The first iteration is the object (Iterable), the second is an iterator (Iterator), a third generator (Generator), where aside generator.

Iterables

Lists, tuples, strings, etc. are iterables dictionaries, may be used for loop through all the elements can be called iterables (Iterable). Iterable class defines a data structure built in the Python, the collections.abc module, we can use this to detect whether iterables

>>> from collections import Iterable
>>> a = [1,2,3]
>>> isinstance(a, Iterable)
>>> True
>>> b = 'abcd'
>>> isinstance(b, Iterable)
>>> True

These data structures are called the Iterable able, because of its internal implementation of the __iter __ () method, so as to be iterative. When we use a for loop, the interpreter calls the built-in iter () function, before the call first checks whether the object implements __iter __ () method, if you call it Gets an iterator (next speak). Adding no __iter __ () method, but realized __getitem __ () method, the interpreter will create an iterator and get the elements in order. If these methods are not found, it will throw a TypeError exception. Here we custom objects, respectively, to achieve the two methods ( getItem (), iter ())

class MyObj:
    def __init__(self, iterable):
        self._iterable = list(iterable)

    def __getitem__(self, item):
        return self._iterable[item]


obj = MyObj([1,2,3])
for i in obj:
    print(i)

As described above, there is no method to achieve __iter__, only achieved __getitem__ method, so called Myobj iterables.
Now we realize __iter__ method used here yield syntax to output values (here requires knowledge generator)

class MyObj:
    def __init__(self, iterable):
        self._iterable = list(iterable)

    def __iter__(self):
        index = 0
        while True:
            try:
                yield self._iterable[index]
            except IndexError:
                break
            index += 1

obj = MyObj([1,2,3])
for i in obj:
    print(i)

Here again let objects called iterables.

Iterator

Iterator can remember the object is a traverse position.
Iterator object began a visit from the first element of the collection until all the elements are accessed session is over. Iterator can only move forward not backward.

1579698-20190621230513320-354680153.png

As shown above, the iterator (the Iterator) may be inherited iteration (the Iterable), and a method iterator __iter__ __next__ methods must be implemented. Wherein __next__ output method for the next element.
Seen from FIG inherited, iterators must be iterator object is not necessarily iterables iterator
iterator has two basic methods: iter () and next ().
We use iter (iterable) to convert iterables iterator to
the next value using the next (iterator) to obtain the iterator

>>> a = [3,4,5]
>>> a
>>> [3, 4, 5]
>>> iter(a)
>>> <list_iterator object at 0x10b130ba8>
>>> iterator = iter(a)
>>> next(iterator)
>>> 3
>>> next(iterator)
>>> 4
>>> next(iterator)
>>> 5
>>> next(iterator)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration

As described above, since the object implements the method __next__, we may be obtained by next (iterator) next value iterators until no value, and raise StopIteration end.

Behind the iterator

Iterator iterator is an abstract base class, which is defined in the _collections_abc.py
Iterator源码follows

class Iterator(Iterable):

    __slots__ = ()

    @abstractmethod
    def __next__(self):
        'Return the next item from the iterator. When exhausted, raise StopIteration'
        raise StopIteration

    def __iter__(self):
        return self

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterator:
            return _check_methods(C, '__iter__', '__next__')
        return NotImplemented

You can see that it implements __subclasshook__ method, that is, without an explicit inheritance Iterator, only need to implement __iter__ and __next__ method can be called Iterator of virtual sub-class . Here highlights Python duck type, to achieve a specific "agreement" can have a certain behavior.
In addition, it also defines __iter__ own way when we use iter (Iterator) directly back to their own, without any treatment.

iter () function of the two Usage

The official explanation is given in the document:

    iter(iterable) -> iterator
    iter(callable, sentinel) -> iterator
    
    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.

The first usage: iter (iterable) -> iterator ( converting iterables iterator)
Second Usage: iter (callable, sentinel) - > iterator ( first argument: Any callable object may be a function the second is the flag value, when an object can be called to return the value the iterator raise StopIteration without tag output value )

>>> from random import choice
>>> values = [1,2,3,4,5,6,7]
>>> def test_iter():
>>>     return choice(values)
>>> it = iter(test_iter, 2)
>>> it
>>> <callable_iterator object at 0x10b130b00>
>>> for i in it:
>>>     print(i)
>>> 7
>>> 1
>>> 7
>>> 3
>>> 1

Flow above code: test_iter function randomly selected from the values ​​in the list a value and returns the call iter (callable, sentinel) function, the sentinel flag value is set to 2, returns a callable_iterator instance, traversing this particular iterator, if the function returns 2 tag value, directly thrown exit the program. This is another little-known usage iter function.

Reproduced in: https: //www.cnblogs.com/PyKK2019/p/11067206.html

Guess you like

Origin blog.csdn.net/weixin_33910434/article/details/93283477