I. Recursion and Iteration
II. What is the iterator protocol
1, the iterator protocol means: the object must provide a next method, the implementation of the method either return to the next item in the iteration, or cause a stopiteration exception, has terminated the iteration (can only go backward can not go forward)
2. Iterable object: an object that implements the iterator protocol (how to implement: define a __iter__() method inside the object)
3, the protocol is a convention, iterable objects implement the iterator protocol, python's internal tools (such as for loop, sum, min, max function, etc.) use the iterator protocol to access the object.
Third, the powerful for loop mechanism in python
The essence of the for loop: loops over all objects, all using the iterator protocol
Explanation:
Sometimes I think, the nature of the for loop is to follow the iterator protocol to access the object, then the for loop object must be iterator ah, yes, then since this, for loop can traverse (string,, list, dictionary, collection, file object), then these types of data must be iterable object ah? But why is there no next() method for defining a list l=[1,2,3,4].
(strings, lists, tuples, dictionaries, collections, file objects) These are not iterable objects, but their internal __iter__ methods are called in the for loop to turn them into iterable objects.
The for loop then calls the __next__ method of the iterable object to fetch the value, and the for loop catches the stoplteration exception, which terminates the iteration.
l=[1,2,3,4,5] # Subscript access method print(l[0]) print(l[7]) #Excess visits are reportedIndexError: list index out of range #Following the iterator protocol diedai=l.__iter__() print(diedai.__next__()) print(diedai.__next__()) print(diedai.__next__()) print(diedai.__next__()) print(diedai.__next__()) print(diedai.__next__()) #StopIteration will be reported if the boundary is exceeded. #for loop access method: The essence of the #for loop is to follow the iterator protocol access, first call diedai.__iter__() method, or directly diedai = iter(l), and then execute (), until the for loop captures the StopIteration to terminate the loop. #For loops all objects are essentially the same thing for i in l: #diedai=l.__iter__() print(l[i]) #i=() # Use while to simulate what a for loop would do. diedai_l=l.__iter__() while True: try: print(diedai_l.__next__()) except StopIteration: print("Iteration complete. Terminate loop.") break
IV. A first look at generators
What is a generator?
can be understood as a datatype that automatically implements the iterator protocol (other datatypes need to call their own built-in __iter__ method), so the generator is the iterable object
Generator categorization and representation in python: (python provides generators in two different ways)
1, generator function: conventional function definition, however, the use of yield statements rather than return statements to return the result. yield statement to return a result at a time, in the middle of no result, hanging function state, so that the next time it is used to leave the place to continue to execute the
2, generator expression: similar to list derivation, however, the generator returns an object that produces results on demand, rather than constructing a list of results at a time
Why use generators and the advantages of producers:
python provides support for deferred operations using generators. By deferred operations, we mean producing results when they are needed, rather than immediately, which is an important benefit of producers
import time # def producer(): # ret=[] # for i in range(100): # (0.1) # ('Bun %s' %i) # return ret # # def consumer(res): # for index,baozi in enumerate(res): # (0.1) # print('The %sth person, ate %s' %(index,baozi)) # # res=producer() # consumer(res) #yield 3 The equivalent of return controls the return value of a function. Another feature of #x=yield is that it accepts a value from send and assigns it to x. # def test(): # print('Here we go') # firt=yield #return 1 first=None # print('first time', firt) # yield 2 # print('second') # # t=test() # res=t.__next__() #next(t) # print(res) # # t.__next__() # # res=(None) # res=('The function stays at the first position, that's where I assign the value to first') # print(res) # def producer(): # ret=[] # for i in range(100): # (0.1) # ('Bun %s' %i) # return ret def consumer(name): print('I'm [%s], and I'm ready to start eating buns' %name) while True: baozi=yield (1) print('%s happily ate [%s] up' %(name,baozi)) def producer(): c1=consumer('wupeiqi') c2=consumer('yuanhao_SB') c1.__next__() c2.__next__() for i in range(10): (1) ('Bun %s' %i) ('Bun %s' %i) producer()
Producer Summary
1, the generator is an iterable object
2、It realizes delayed calculation and memory saving
3, the essence of the generator and other data types, are the implementation of the iterator protocol, except that the generator is attached to a delay in the calculation of memory-saving benefits, the rest of the iterative object can not have this benefit
V. Generator Expressions and List Parsing
#1, ternary expressions name="alex" name="yangyl" res="1" if name=="yangyl" else "2" print(res) egg_list=["Egg%s" %i for i in range(10) ] #list parsing print(egg_list) # Use the producer to get egg_two=("Egg%s" %i for i in range(10)) # Producer expressions print(egg_two) print(egg_two.__next__()) print(next(egg_two)) #next()Essentially, it's a call to the__next__
Summary:
1, replace [] with () in the list parsing to get the generator expression
2, list parsing and generator expressions are a convenient way of programming, except that generator expressions are more memory-saving
3. python not only uses the iterator protocol to make for loops more general. Most of the built-in functions also use the iterator protocol to access objects. For example, the sum function is a built-in function in python that uses the iterator protocol to access objects, and the generator implements the iterator protocol, so we can directly calculate the sum of a series of values this way:
s1=sum(x ** 2 for x in range(4))
print(s1)
Instead of having to construct a list
s2=sum([x ** 2 for x in range(4)])
print(s2)
This is the whole content of this article.