Generator & iterator

WeChat official account is searching for the program yuan Xiaozhuang. It pays attention to how to develop a family breadwinner by python.

preface

String, list, tuple, dictionary and set all belong to iteratable objects. This article will introduce what iteratable objects are. Let's Polish blingbling's big eyes and see together!

Iterator objects

Iterator is a tool used to iterate values. Iteration is a repeated process, but each repetition continues based on the last result. Simple repetition is not iteration, as shown in the following code:

while True:
    info = input('your name>>>')
    print(info)

The following code is an iterative process, which not only repeats the cycle, but also based on the last result each time:

best_language = ['python', 'java', 'c']

index =  0
while index < len(best_language):
    print(best_language[index])
    index += 1

The above method takes values according to the index, which can also be called iterative value, but how to take values for data types without index, such as dictionaries? Therefore, the python interpreter must provide a way that does not depend on the index value, which is the iterator.

To know what an iterator is, you need to know what an iteratable object is. Let's have a look!

Iteratable object

In the previous introduction to data types, the iterative object is defined in this way - the object that can be looped by for is the iterative object. The iterative object includes string, list, tuple, dictionary, set, open file, etc. in fact, the iterative object has a more specific definition method - except in the built-in method__ iter__ Method is an iteratable object.

# The file object is an iteratable object
with open(r'F:\FullStack\Python_based\info') as f:
    f.__iter__()

Call in an iteratable object__ iter__ The result returned by the method is an iterator object, and the iterator object also has a more specific definition method - except in the built-in method__ iter__ And__ next__ The object of the method is the iterator object..

For example, the open file itself is an iterator object, which executes the function of the iterator object__ iter__ Method is still the iterator object, and the iterator object is executed__ next__ Method gets the next value in the iterator object.

Executing iterator objects__ next__ Method, when the value in the iterator is taken, it will throw an exception of StopIteration. The iterator can be understood as a hen that can lay eggs. Assuming that the hen can only lay three eggs in a lifetime, after laying these three eggs, the hen will die and cannot continue to lay eggs.

>>> list1 = [1, 2, 3]
>>> iterator = list1.__iter__()  # Equivalent to iterator = iter(list1)
>>> iterator.__next__()   # Equivalent to next(iterator)
1
>>> iterator.__next__()
2
>>> iterator.__next__()
3
>>> iterator.__next__()  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module> StopIteration 

You can use the loop to realize the above repeated output: exception handling (which will be described in detail later). When an exception occurs, the loop will be terminated without error.

list1 = [1, 2, 3]
iterator = list1.__iter__()
while True:
    try:  # Try exception is the syntax to catch exceptions
        print(iterator.__next__())
    except StopIteration:
        break

# Loop the iterator again
while True:
    try:
        print(iterator.__next__())  # There is no value here
    except StopIteration:
        break

There will be a problem here. When you cycle the iterator again, you can't get the value of the iterator. The reason is that the hen of the iterator dies after laying eggs. Do you think it's possible to lay eggs again? If you still want to take values in this iterator, the solution can only recreate an iterator.

Advantages and disadvantages of iterators

advantage:

1. It provides a unified iterative method for sequential and non sequential data types

2. The iterator object represents a data stream. You can call next only when necessary to calculate a value. For the iterator itself, there is only one value in memory at the same time, so it can store infinite data streams. For other container types, such as columns, you need to store all elements in memory, which is limited by the size of memory, The number of values that can be stored is limited.

Disadvantages:

1. Only one value can be taken down, not back to the beginning. It is more like "one-time". The only goal after the iterator is to repeatedly execute the next method until all the values are taken, otherwise it will stay in a certain position and wait for the next call;

2. If you want to iterate over the same object again, you can only call it again__ iter__ Method to create a new iterator object. If two or more loops use the same iterator, only one loop will get the value.

for loop principle

The object of the for loop must be an iteratable object, so the for loop is also called an iterator loop. The principle of the for loop is based on the iterator.

First, the for loop passes the iteratable object through the call__ iter___ Method into an iterator object;

Then, call the built-in method of the iterator object. next__ Get the next value in the iterator;

Finally, the loop goes back to the previous step until the value of the iterator is exhausted, an exception is caught and the loop is terminated.

list1 = [1, 2, 3]
iterator = list1.__iter__()
while True:
    try:
        print(iterator.__next__())
    except StopIteration:
        break

Generator & yield

The return keyword in the function generator will be used to replace the return code of the function with the return keyword in the function generator, and then the return code of the function will not be obtained.

The resulting generator object has built-in methods__ iter__ And__ next__, Therefore, the generator itself is a custom iterator.

# Customize a generator that can generate many numbers, just like range
def my_range(start, stop, step=1):
    while start < stop:
        yield start
        start += step

res = my_range(1,10,2)
print(res)  # <generator object my_range at 0x0000023D283A10B0>
print(res.__iter__())  # <generator object my_range at 0x0000023D283A10B0>
print(res.__next__())  # 1

Since the generator is an iterator, you can use the for loop to iterate on the generator:

for i in my_range(1, 10, 2):
    print(i)

If the return method of the return function is different from that of the return function, the return method of the return function can be used to replace the return value of the return function. However, if the return method of the return function is different from that of the return function.

Ternary expression

It is necessary to add a knowledge point - ternary expression, which is a simplification of the branch structure. Examples are as follows:

def func(x,y):
    if x > y:
        return x
    else:
        return y

res = func(1,2)
print(res)

The branch structure in the above code can be simplified by ternary expression. The syntax structure of ternary expression is as follows:

res = Value returned when condition holds if condition else The returned value is invalid

Ternary expression is a scheme to simplify code provided by python. Therefore, the above code can be simplified to:

def func(x, y):
    res = x if x > y else y
    return res

Generative formula

Like ternary expressions, generative expressions are a code simplification scheme provided by python, which can be used to quickly generate lists, dictionaries and generators. There are the following types of generative expressions:

List generation

The list generation formula can quickly generate a list. The syntax is as follows:

list1 = [i for i in iterable if condition]  # if statements are optional, according to the actual scenario
 amount to:
list1 = []
for i in iterable:
    if condition:
        list1.append(i)

For example, for the following requirements, list generation can be used to solve them in one line:

# Capitalize all the elements in the following list
l = ['python', 'java', 'go']
# Mode 1:
new_list = []
for i in l:
    new_list.append(i.upper())
    
# Method 2: it can be solved in one line by using list generation formula
new_list = [i.upper() for i in l]
print(new_list)  # ['PYTHON', 'JAVA', 'GO']

Dictionary generation

Dictionary generation can quickly initialize a dictionary:

key = {'1','2','3'}
dic = {i:None for i in key}
print(dic)
# give the result as follows
{'3': None, '2': None, '1': None}

Generator generator

To create a generator, you can use the function with the yield keyword. The other is to use the generator generator generator. The syntax format of the generator generator generator is the same as that of the list generator. You only need to replace [] with ()

Note that the comparison list generator returns a list, and the generator expression returns a generator object. The natural advantage is to save memory. Only one value is generated at a time and stored in memory.

>>> [i for i in range(4)]
[0, 1, 2, 3]
>>> (i for i in range(4))
<generator object <genexpr> at 0x0000026E4194BD60>

Keywords: Python

Added by mu-ziq on Tue, 08 Feb 2022 12:21:47 +0200