Iterators and generators, like the decorators in the previous article, are a perennial problem for me. Usually when they come across it, they search for it, only to see it in a bunch of various introduction blogs, and then forget about it. Are you the same way?

As the saying goes: a good memory is better than a bad pen, although now basic not how to write with a pen, but still want to tidy up, at least later I will not search.

List_a = [1, 2, 3, 4]

list_a = [1, 2, 3, 4]

for i in list_a:
    print(i)
Copy the code

run

1
2
3
4
[Finished in 0.1s]
Copy the code

As you can see, the for loop iterates over each element in the list, printing it out. So what’s going on behind the for loop?

Container, iterable, iterator

Words that may sound strange, but you are absolutely familiar with them.

In Python, everything is an object, the abstraction of an object is a class, and a collection of objects is a container.

There are many common containers in Python, such as list:[0, 1, 2], set:([0, 1, 2]), dict dict:{0:0, 1:1, 2:2}, and tuple(0, 1, 2). These are units with multiple elements grouped together, and differ in how the internal data structures are implemented.

All containers are iterable. You can use the for loop to iterate over the above containers.

That’s what iterators are used to find elements. Iter () creates an iterator.

Iterators provide a next() method that returns the next object each time you call it, or StopIteration, which means there are no more objects to give you.

list_a = [1, 2, 3, 4] list_a # create iterator print(next(it)) # create iterator print(next(it)) print(next(it)) print(next(it)) print(next(it)) print(next(it)) print(next(it)) print(next(it)) print(next(it))Copy the code

As a result, the first four print entries return normally, but the fifth iteration error appears because the four entries in the list are already returned.

1 2 3 4 Traceback (most recent call last): File "D:\ exercise \demo_iterator.py", line 9, in <module> print(next(it)) StopIteration [Finished in 0.1s with exit code 1]Copy the code

Ii. Generator

What is a generator? To be blunt: generators are lazy iterators.

List_a = [1, 2, 3, 4]; list_a = [1, 2, 3, 4]; list_A = [1, 2, 3, 4];

But all of these elements are going to be stored in memory, these are only four elements, what if there are tens of millions, hundreds of millions of elements? I don’t have to use all of them the first time, I just have to generate one of them when I call next(), and it takes up a lot of memory.

The generator is created so that the next variable is generated when next() is called. Generators are written simply in parentheses, such as enclosing a list generator :(I for I in range(10000)), which initializes a generator.

print([i for i in range(10)])

print(i for i in range(10))
Copy the code

The time list above is a generator, and the one below is a generator. The difference is [] and (). Running results:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] < Generator Object <genexpr> at 0x033383A8>Copy the code

The yield keyword

In addition, functions can be generators, and the secret is the yield keyword, such as:

def gen():
    a = 0
    while a < 100:
        yield a
        a += 1

test = gen()
print(next(test))
print(next(test))
print(next(test))
print(next(test))
Copy the code

Running results:

0
1
2
3
[Finished in 0.1s]
Copy the code

The yield keyword can be understood as: when a function runs to this line, the program will pause at this point, yield equals return, and at the next iteration, the execution will start at the yield line.

So, I called print four times, starting at zero.