1, Iterator
On the surface, an iterator is a data stream object or container. When using the data in it, one data is taken from the data stream at a time until the data is taken, and the data will not be reused
__iter__():
__next__():
The "_iter_ ()" method returns the object itself, which is the requirement for the for statement to use the iterator
The "_next_ ()" method is used to return the next element or data in the container. When the data in the container is exhausted, a StopIteration exception should be thrown
Any class, as long as it implements or has these two methods, can be called iterator or iterative. When using it as an iterator, you can use for to traverse (iterate) it. The example code is as follows
for item in iterator:
pass
In each loop, the for statement takes a data from the iterator sequence and assigns it to item for use or processing in the loop. Formally, it is exactly the same as traversing tuples, lists, strings, dictionaries and other sequences. class MyIterator: # custom class iterator myiterator # def__ init__ (self, x = 2, xmax = 100): # define construction methods and initialize instance properties
self.__mul,self.__x = x,x self.__xmax = xmax def __iter__(self): #Define the iterator protocol method and return the class itself return self def __next__(self): #Define iterator protocol method if self.__mul and self.__x != 1: self.__mul *= self.__x if self.__mul <= self.__xmax: return self.__mul #Return value else: raise StopIteration #lead StopIteration error else: raise StopIteration if __name__ =='__main__': myiter = MyIterator() #Instantiate iterator MyIterator for i in myiter: #Traverse and output values print('The iterative data elements are:',i)
#results of enforcementThe iterative data elements are: 4
The iterative data elements are: 8
The iterative data elements are: 16
The iterative data element is: 32
The iterative data elements are: 64
[code description]
It can be seen from the code that if you need to generate a sequence of a large range of numbers and use lists or tuples for one-time generation, it must occupy a large number of space
The memory space has great "lethality" to the system. Using iterators, you can generate one for each call, which obviously saves a lot of memory space.
2, Generator
The generator object is a function defined by using the yield keyword, so the generator is also a function. The generator is used to generate a sequence of values for use in iterations
def myYield(n): #Define a generator(function) while n < 5: print('start') yield n #yield This step begins to return n After entering the next step from print('one...')Start execution print('one...') n += 1 if __name__ == '__main__': for i in myYield(1): #for Loop traversal generator print('Traversal value:',i) print() my_yield = myYield(0) #Generate a build object print('The generator object has already been instantiated') print(my_yield.__next__()) #Manually call its special method to obtain a value in the sequence print(my_yield.__next__()) #The second manual call continues to output yield Output after #results of enforcement start Traversal value: 1 one... start Traversal value: 2 one... start Traversal value: 3 one... start Traversal value: 4 one... The generator object has already been instantiated start 0 one... start 1
[code description]
The generator contains a yield statement, which can be traversed directly with for or called manually__ next__ () method
The yield statement is the key statement in the generator. When the generator is instantiated, it will not execute immediately, but wait for its call__ next__ () method starts running, and when the program runs the yield statement, it will "hold", that is, it will maintain its current state and stop running, and wait for the next traversal to resume running
Generator and coroutine
Using the send() method to reset the generator's generation sequence, you can send digital strings, etc
def consumer(): #Define a consumer model (generator collaboration) print('Waiting to receive processing tasks...') while True: data = (yield) print('Received task:',data) #Simulate accepting and processing tasks #Here you can call the function to complete the task def producer(): #Define a producer model c =consumer() c.__next__() for i in range(3): print('Send a task...','task%d' %i) c.send(1) #Send number "1" c.send('task%d' %i) #Send string if __name__ == '__main__': producer() #Call function producer #results of enforcement Waiting to receive processing tasks... Send a task... Task 0 Received task: 1 Task received: task 0 Send a task... Task 1 Received task: 1 Received task: Task 1 Send a task... Task 2 Received task: 1 Received task: Task 2
[code description]
The two functions defined in the code represent the generator and the consumer model respectively, and the consumer model is actually a generator. In the generator model function, each loop simulation sends a task to the consumer model (generator), and the generator can call related functions to process the task, which is to complete this task by using the "hold" property of the yield statement
Trimmer: