python iterator, generator, decorator

Posted by jpoladsky on Fri, 31 Dec 2021 12:27:02 +0100

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 enforcement


 The 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:

Topics: Python