current position:Home>Python notes (16): generators and iterators

Python notes (16): generators and iterators

2022-01-30 15:41:20 A bowl week

Little knowledge , Great challenge ! This article is participating in “ A programmer must have a little knowledge ” Creative activities .

Hello everyone , I am a A bowl week , One doesn't want to be drunk ( Internal volume ) The front end of the . If you are lucky enough to get your favor , I'm very lucky ~

generator

Now you can create a list directly through the generator , But because of the limitation of memory , The capacity of the list must be limited , If we need a list of hundreds of elements , But only a few of them are visited each time , If the remaining elements are not used, it is a waste of memory space .

This is the time generator Generator) It works , He keeps generating new data according to some algorithm , Until a specified condition is met

There are several ways to get the generative expression :

  1. Get the generator through the list generator , The sample code is as follows :

    g = (x for x in range(10))  #  Generate a list of columns [] Change into ()
    #  Print its type 
    print(type(g))  # <class 'generator'>
    #  Call its element 
    print(g.__next__())  # 0
    print(g.__next__())  # 1
    print(g.__next__())  # 2
    print(g.__next__())  # 3
    print(g.__next__())  # 4
    #  Use .__next__ Method call 
    print(next(g))  # 5
    print(next(g))  # 6
    print(next(g))  # 7
    print(next(g))  # 8
    print(next(g))  # 9
    #  Use next() Method call for 
    print(next(g))  #  When the data is not called, an error will be reported  StopIteration
     Copy code 

    Call as many as you need , If it is not called, it will not generate , It won't take up memory space , You can use a loop structure to call... As needed

    g = (x for x in range(10))  #  Generate a list of columns [] Change into ()
    skip = True  #  Judge the condition 
    count = 0  #  Call the number 
    while skip:
        count += 1  #  Cycle time +1
        print(next(g))
        if count > 9:
            break  #  Out of the loop 
     Copy code 
  2. Use functions with the help of yield Keyword to complete a generator , Generate Fibonacci sequence Before 20 Number , The sample code is as follows :

    def fun(length):
        a, b = 0, 1
        for _ in range(length):
            a, b = b, a + b
            yield a
    
    
    fib = fun(20)
    print(type(fib))  # <class 'generator'>  #  Print type 
    count = 0
    while count < 20:
        # 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
        print(next(fib), "", end="")
        count += 1
     Copy code 

    The process is as follows :

    In the process of execution , encounter yield Keywords will be suspended , The next call will continue to execute from the last suspended position , Because it's a circular statement , All will jump directly to for sentence

    If you're calling yield, You need to pass it a value , Then use .send() The method . The sample code is as follows :

    def fun(num):
        n = 0
        for i in range(num + 1):
            n += i
            ret = yield n
            print(f" This is a + To {ret} Of the {i + 1}  Time ")
    
    
    g = fun(3)
    print(g.send(None))
    print(g.send('3'))
    print(g.send('3'))
    print(g.send('3'))
    '''
    --- Output results ---
    0
     This is a + To  3  Of the  1  Time 
    1
     This is a + To  3  Of the  2  Time 
    3
     This is a + To  3  Of the  3  Time 
    6
    '''
     Copy code 

    send The addition of can make the generator more flexible , But it should be noted that the first time you call the generator send() When the method is used , The parameter can only be None, Otherwise, an exception will be thrown . Of course, you can also call send() Method is called once before next() Method , The purpose is to let the generator enter yield expression .

Iterators and iteratable generators

Iteratable objects are generators 、 Tuples 、 list 、 aggregate 、 Dictionaries and strings

adopt collections Of Iterable Function combination isinstance(object, classinfo) To determine whether an object is not an iteratable object

Iteration is a way to access collection elements . An iterator is an object that remembers the traversal location . The iterator object is accessed from the first element of the collection , Until all elements are accessed . Iterators can only move forward and not backward . Well, generators are also iterators .

Can be next () The object that function calls and returns the next value continuously is called an iterator : Iterator , have access to isinstance() Determine whether an object is Iterator object :

Be careful : Iteratable is not necessarily a generator , But the generator must be iterative .

The tuple 、 list 、 aggregate 、 Dictionaries and strings Iterable become Iterator have access to iter() function

Iterable and Iterator**** The difference between yes Iterable It can be used as for A generic term for circular objects ; and Iterator The object needs to be next() The function call keeps returning the next data , Thrown until no data StopIteration error , And you won't know its length until then , therefore Iterator The calculation of is inert , Only next() The function calls him to return the result ,Iterator It can even represent an infinite data flow , For example, all natural numbers .

from collections.abc import Iterable, Iterator
a = [1, 2, 3]
b = {1, 2, 3}
c = (1, 2, 3)
d = "123"
e = 123
f = (x for x in range(5))
#  Print data type 
print(type(a))  # <class 'list'>
print(type(b))  # <class 'set'>
print(type(c))  # <class 'tuple'>
print(type(d))  # <class 'str'>
print(type(e))  # <class 'int'>
print(type(f))  # <class 'generator'>
print("-" * 20)

#  Print whether it is an iteratable object 
print(isinstance(a, Iterable))  # True
print(isinstance(b, Iterable))  # True
print(isinstance(c, Iterable))  # True
print(isinstance(d, Iterable))  # True
print(isinstance(e, Iterable))  # False
print(isinstance(f, Iterable))  # True
print("-" * 20)
#  Except that strings are iteratable objects 

#  Print whether it is an iterator 
print(isinstance(a, Iterator))  # False
print(isinstance(b, Iterator))  # False
print(isinstance(c, Iterator))  # False
print(isinstance(d, Iterator))  # False
print(isinstance(f, Iterator))  # True
#  Only f( generator ) Is the iterator 
print("-" * 20)


#  adopt iter() Turn iterations into iterators 
print(isinstance(iter(a), Iterator))  # True
print(isinstance(iter(b), Iterator))  # True
print(isinstance(iter(c), Iterator))  # True
print(isinstance(iter(d), Iterator))  # True
 Copy code 

copyright notice
author[A bowl week],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201301541171236.html

Random recommended