Before we look at what iterators and generators are, let’s look at the concept of containers. For all objects, a container is a collection of objects. Lists, progenitors, dictionaries, and so on are containers. You can visualize a container as a unit with multiple elements together; The difference between containers lies in how the internal data structures are implemented. You can then choose containers of different time and space complexity for different scenarios.
All containers are iterable. Iterators are used to iterate over elements in a container. Iterators provide a method for next. After calling this method, you either get the next object of the container or a StopIteration error. You don’t need to specify an index for an element like a list, because dictionaries and collections don’t have indexes.
For iterable objects, we can return an iterator through iter(), which can then be iterated through next(). Let’s look at the following code to understand.
S = set ([1, 2, 3, 4, 5]) it = iter (s) print (it. __next__ ()) print (it. __next__ ()) print (it. __next__ ())Copy the code
Its outputs are 1, 2, and 3, which are elements in the output set one by one.
So what is a generator? We know that in an iterator, if we want to enumerate its elements, those elements need to be generated beforehand. Here, let’s take a look at a simple example.
Def show_memory(temp): pid = os.getpid() p = psutil.Process(pid) info = p.memory_full_info() memory = info.uss / 1024. / 1024 print('{} memory used: {} MB'.format(temp, memory)) def iterator(): show_memory('initing iterator') list_1 = [i for i in range(10000)] show_memory('after iterator initiated') print(sum(list_1)) show_memory('after sum called') def generator(): show_memory('initing generator') list_2 = (i for i in range(10000)) show_memory('after generator initiated') Print (sum(list_2)) show_memory('after sum called') iterator() Generator () 5.58984375 MB After iterator initiated memory used: 6.0234375 MB 49995000 after sum called memory used: 6.0234375 MB initing Generator memory Used: 6.0234375 MB After Generator initiated Memory used: 6.0234375 MB 49995000 after sum called memory used: 6.0234375 MBCopy the code
In iterator(), a list of 10,000 elements is generated by [I for I in range(10000)]. As you can see from the code, each element takes up a huge amount of memory and an OOM error occurs if it runs out of memory. However, we don’t need to keep all these things in memory at the same time, like summing up elements, we just need to know what each element was at the moment it was added, and then we can throw it away. Hence the concept of generators, which generate the next variable only when you call the next() function. Generators are written in Python in parentheses (I for I in range(10000)), which initializes a generator. This way, you can clearly see that generators don’t take up as much memory as iterators and are only called when they are used. Moreover, the generator does not need to run a generation operation when it is initialized, and the generator() function saves generating 10,000 elements at a time compared to Iterator. So you don’t need a lot of memory.
Ok, now that we know what generators and iterators are, let’s look at an example like this:
Given a list and a specified number, find the number’s position in the list. If you’re familiar with the following code, it’s common practice to enumerate each element and its index, add result, and return.
def index(list1, target): result = [] for i, num in enumerate(list1): if num == target: Result.append (I) return result print(index([2, 3, 6,7,9,0,2,6], 6))Copy the code
So what can we do with iterators? As follows:
def index(list1, target): for i, num in enumerate(list1): if num == target: Yield I print (list (index ([2, 3, 6,7,9,0,2,6], 6))) output: [2, 7)Copy the code
The above index function returns a generator object that needs to be converted to a list and then printed.
1. A container is an iterable. The iterable calls iter() to get an iterator. Iterators can be used to get the next element via the next() function to support traversal.
A generator is a special kind of iterator. With generators, you can write cleaner code; The proper use of generators can reduce memory footprint and increase program speed.
If you have any questions, please leave a comment and discuss with me.
For more interesting knowledge, please scan the code to follow the public number.