Iterable Objects, Generators, Iterators

Iterable Objects

  • str,tuple,dict,list,set,bytes are iterative objects
  • The result of range is a range object, an iterative object
  • Essentials of Iterable Objects:
    • When you iterate over an iterative object, you essentially get an iterator provided by that object, then use that iterator to get each data in the object in turn.
    • That is, an object with u iter_ method is an iterative object.

iterator

  • Any object in python that implements the u iter_ and u next_ methods can be called an iterator.

  • The _iter () method returns a special iterator object, and the () iterator () returns a body, which implements the u next () method to return the next value and the completion of the iteration with the StopIteration exception identifier.

  • An iterator is a state-dependent object that records the location of iterations.

  • str / bytes / list / tuple / dict / set_body is not an iterator, they do not have u next () body, but have u ITER (), and u ITER ()method to convert body to iterator

  • In [1]: s='asdfghh' #Strings are iterative objects
    
    In [2]: si=s.__iter__() #Calling the u iter_() method returns an iterator
    
    In [3]: next(si)
    Out[3]: 'a'
    
    
  • The u next() method (next() in Python 2) returns the next iterator object.

  • Execution order:

class A:
    def __init__(self):
        self.count=10

    def __iter__(self):
        print('implement __iter__')
        return self
    def __next__(self):
        print('implement __next__')
        if self.count>0:
            self.count-=1
            return self.count
        else:
            print('Stop Iteration')
            raise StopIteration
for i in A():
    print('i=',i)
    
#################################Printed results
'''
//Execute u iter_u Execute u iter_u first, returning an Iterable object
//Execute u next_u
i= 9
.
.
.
//Execute u next_u
i= 1
//Execute u next_u
i= 0
//Execute u next_u
//Stop Iteration


'''

  • Exercise: Using iterators to implement Fibonacci series
class FibonaccIterator(object):
    def __init__(self,n):
        self.n=n
        self.current=0
        self.num1=1
        self.num2=1

    def __iter__(self):
        return self
    def __next__(self):
        if self.current < self.n:
            x=self.num1
            self.num1,self.num2=self.num2,self.num1+self.num2
            self.current +=1
            return x
        else:
            raise StopIteration

generator

  • generator:Generator is a special iterator that does not require defining u iter and u next u

  • Return a function with the yield keyword

  • Generator can record the current running state by itself, and will continue executing from the previous location the next time it starts

  • When a yield statement executes, the generator object gives the interpreter control and the generator itself hangs

def foo():
    print(111)
    yield 222   #yield will give the interpreter control and suspend
    print(333)
    yield 444
    print(555)

n=foo() #Having yield is a special function, just encapsulating a generator object
#No results will be executed

next(n)#Only next calls will have results
x = next(n)  # Print 111, return 222
y = next(n)  # Print 333, return 444
z = next(n)  # Print 555, throw exception

  • In addition to using yield to implement the generator, there is another way to implement the generator

    • In [1]: x=(i for i in range(10))
      
      In [2]: type(x)
      Out[2]: generator
      
  • Exercise: Using generator to implement Fibonacci series

def gen_fib(n):
    num1=num2=1
    current=0
    while current < n:
        yield num1
        num1,num2=num2,num1+num2
        current+=1
F=gen_fib(12)
for i in F:
    print(i)

Handwriting a range

class Range:
    def __init__(self, start, end=None, step=1):
        if end is None:
            self.start = 0
            self.end = start
        else:
            self.start = start
            self.end = end
        self.step = step

    def __iter__(self):
        return self

    def __next__(self):
        if self.start < self.end:
            current = self.start
            self.start += self.step
            return current
        else:
            raise StopIteration


for i in Range(5):
    print(i)

for i in Range(5, 10):
    print(i)

for i in Range(10, 20, 3):
    print(i)

Benefits of Generator with Iterator

  • Save memory
    • You can use the getsizeof method in the sys standard library to see how much memory is being used
In [4]: x=range(10000)

In [5]: y=[i for i in range(10000)] #List Derivation

In [6]: import sys

In [7]: sys.getsizeof(x)
Out[7]: 48

In [8]: sys.getsizeof(y)
Out[8]: 87624
  • Inertia Evaluation (Inertia Evaluation Thought in Lisp)
Two original articles have been published. 1. Visits 17
Private letter follow

Keywords: Python

Added by simcoweb on Sat, 22 Feb 2020 05:47:57 +0200