Write the same, let's take a look at iterator generators

iterator

iterable

An object with an __iter__ method is iterable, and they can all be evaluated using a for loop (this is not true, the __iter__ method should return an iterator).

E.g:

print('__iter__' in dir([])) # True
print('__iter__' in dir(())) # True
print('__iter__' in dir("wfdsf")) # True
print ('__ iter__' in dir (123)) # False

iterator

An iterable object with an internal __next__ method is an iterator, and an iterator is a part of an iterable.

Iterable objects call __iter__() to form an iterator

ret = "adc".__iter__()
ret2 = ret .__ iter __ ()
# view type
print(type(ret)) # <class 'str_iterator'>
# View the difference between an iterable and an iterator
print(set(dir("abc".__iter__()))-set(dir("abc")))
# {'__next__', '__setstate__', '__length_hint__'}
# See the difference between iterator and iterable object's __iter__ method
print (ret == ret2) # True
# Use the __next__ method to get the value from the iterator
print(ret.__next__()) # a
print(ret.__next__()) # b
print(ret.__next__()) # c
print(ret.__next__()) # Throws StopIteration exception

#Use the while loop to implement the function of the for loop
l = [1,2,3,4]
l_iter = l .__ iter __ ()
while True:
    try: #handle exception
        item = l_iter.__next__()
        print(item)
    except StopIteration:
        break

Determine if an object is an iterator or an iterable

method one,

Determine whether the method __iter__ exists in the method of the variable, and the existence is iterable (unless you write a class to implement this method yourself)

Determine whether the method __next__ exists in the method of the variable, and the existence is an iterator (unless you write a class yourself that implements this method)

print('__iter__' in dir([1,2,3,4])) # True
print('__next__' in dir([1,2,3,4])) # False

 Method 2

Determine if an object is an iterator or an instance of an iterable object

from collections import Iterable # The class of the iterable object
from collections import Iterator # iterator class
print(isinstance([1,2,3,4],Iterable)) # True

str_iter = [1,2,3,4].__iter__()
print(isinstance(str_iter,Iterator)) # True

print(isinstance([1,2,3,4],Iterator)) # False

Features of iterators

  • lazy operation
  • The value is taken from the front to the back, the process is irreversible and cannot be repeated
  • save memory

Builder

The essence of generators is iterators

So generators have the characteristics of iterators, but generators are code written by ourselves

generator function

A function that contains the yield keyword is a generator function.

Yield can return values ​​from functions for us, but yield is different from return. The execution of return means the end of the program. Calling the generator function will not get the specific value returned, but an iterable object. Every time you get the value of this iterable object, you can push the execution of the function and get a new return value. until the end of the function execution.

def generator_fun1(): # This function is a generator function
    yield 1
    yield 2
x=genrator_fun1()#x is a generator
print(type(x)) # <class 'generator'>
print(x.__next__()) # 1
print(x.__next__()) # 2

Example of listening for appending at the end of a file:

#Listen to the example of appending at the end of the file
def tail():
    f = open('file','r',encoding='utf-8')#Open the file
    f.seek(0,2) move the cursor to the end
    while True:
        line = f.readline()#read content
        if line: #content is not empty
            yield line#returns the read content
        import time
        time.sleep(0.1)
g = tail()
for i in g:
    print(i.strip())

send method

The send method can pass data to the generator and return a yield value

def func():
    a = yield 5
    # The value of send will be received by the variable before yield, because the expression will first calculate the value on the right, and will not be executed later
    # So it is said that at least one yield can be sent, otherwise a TypeError exception will be thrown
    yield a

g = func()
num = g.__next__()
print(num) # 5
num2 = g.send('alex')
print(num2) # alex

Example of finding the average

def init(func): #Generator's pre-fire decorator
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)   #func = averager
        g.__next__() # Execute __next__() first
        return g
    return inner

@init
def averager(): # find the average
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average # return average, send value to term
        total += term # sum
        count += 1 # times
        average = total/count # average

g_avg = averager()
print(g_avg.send(10))#10
print(g_avg.send(30))#20

yield form usage

def func():
    a = 'AB'
    b ='CD'
    yield from a# 相当于for i in a:yield i
    yield from b# 相当于for i in b:yield i

# 'A','B','C','D'
# returned 4 times
g = func()
for i in g:
    print(i)

generator expression

#list comprehension
y = [1,2,3,4,5,6,7,8]
x = [1,4,9,16,25,36,49,64]
#Get a list x from list y
x = [i*i for i in y]#List comprehension


#generator expression
#Replace the list comprehension [] with () to become a generator expression.
l = ['鸡蛋%s'%i for i in range(10)]
print(l)#List expression to get a list
#Generator expression gets a generator
laomuji = ('鸡蛋%s'%i for i in range(10))
for egg in laomuji:
    print(egg)

Using __iter__ in Object Orientation

The essence of the for loop is to call the __iter__() method of an object, get an iterator, use the __next__() method to get the value, and do exception handling. When we define our own class, we can also implement __iter__ by ourselves () method so that our object can be looped.

class For:
    def __init__(self,list):
        self.list = list
    def __iter__(self):
        for i in self.list:
            yield i

l = For([1,2,3,4,5,6])
for i in l:
    print(i)

  This method is used in the form component. When we loop the form instance, its __iter__ method loops through its field list, and the value yield will come

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325144384&siteId=291194637