preface
Iteratable objects, iterators, generators, I don't know if you have a very familiar feeling when you first see these nouns, and then quickly look for the differences between these words in your mind, but after looking for a long time, you don't seem to find it, and the original clear concept becomes blurred.
Anyway, I had this feeling at the beginning, but now I still feel a little dizzy after reading this chapter. Hahaha, but I'd better take advantage of the hot iron and review and consolidate it. It should be clearer!
First of all, let's take a look at their respective definitions. Here I will refer to the contents of the book, and then define the three in combination with my own understanding.
Iteratable object
First, we can ask such a question: what is an iteratable object? This may be more abstract and difficult to understand. Let's put it another way: what behavior objects are iteratable objects? In this way, you may be much clearer (thanks to the advantages of python itself: in python, when we say what an object belongs to, we don't look at its definition, but what kind of behavior it has).
Here are some chestnuts:
a = [1, 2, 3] # list b = 'hello' # character string class Fruit: # class fruits = ['apple', 'peach', 'banana'] def __getitem__(self, item): return self.fruits[item] if __name__ == '__main__': for i in a: print(i, end=' ') print() for i in b: print(i, end=' ') print() for i in Fruit(): print(i, end=' ')
The list can be traversed, so it can be iterated and is an iteratable object;
It can iterate, so it can iterate;
Why can Fruit objects also be traversed? "Fluent python" learning notes: eccentric python? You may find the answer in this article!
So let's summarize: objects that can iterate over the values in an object by using a for like loop are iteratable objects. What are the unique methods or properties of these objects?
Generally speaking, objects with the following properties or methods are iteratable objects:
- Realized__ iter__ Object of method
- Implemented__ getitem__ Object of method
- Sequences (such as list, str, array, dict, set, etc.) are iteratable objects
An object that satisfies any of the above three conditions is an iteratable object!
iterator
From the definition of the interface, an iterator is an object that implements parameterless__ next__ Method to return the next element in the sequence; If there are no elements, a StopIteration exception is thrown.
The definition of iterator is relatively simple, which can be summarized in one sentence: as long as it is implemented__ next__ All objects are iterators! (of course, _next _'s behavior is to get the next element!)
Here is a chestnut:
import re import reprlib from typing import Iterator class Sentence: RE_WORD = re.compile('\w+') def __init__(self, text): self.text = text self.words = self.RE_WORD.findall(self.text) def __getitem__(self, item): return self.words[item] def __len__(self): return len(self.words) # reprlib.repr is used to generate a short string representation of large data structures def __repr__(self): return f'Sentence({reprlib.repr(self.text)})' def __iter__(self): return SentenceIterator(self.words) #Convert to iterator class SentenceIterator: def __init__(self, words): self.words = words self.index = 0 def __next__(self): try: word = self.words[self.index] except IndexError: raise StopIteration() self.index += 1 return word def __iter__(self): return self if __name__ == '__main__': text = 'we price the things when we have lost them.' sentence = Sentence(text) sentence_iter = sentence.__iter__() # Call__ iter__ Method to iterator print(isinstance(sentence_iter, SentenceIterator)) #The result is True while True: try: print(next(sentence_iter),end=' ') #Value through next except: pass
You can see that the object of sentinceiterator is a typical iterator because it implements__ next__ method!
generator
There are two ways to get the generator:
- Generated by a function containing the yield keyword
- Generated by generator expression
Take chestnuts for example:
#generator function def func(): for i in range(10): yield i if __name__ == '__main__': a = (i for i in range(10)) #Generator Expressions print(type(a),next(a)) b=func() print(type(b),next(b))
You can see that the objects obtained through the function func and generator expression belong to the generator class and are generator objects, and you can get the next element through the next() method! So there's another conclusion: all generators are iterators!
summary
Of these three objects, the iteratable object may be the best understood. The iterator and generator may always feel the same. From the definition of the interface, we can see that both iterator and generator are implemented__ next__ Method, so it can be said that the generator is also an iterator, but in terms of definition, there are only those two definition methods of the generator, which is also a special definition method. This may be the difference between the generator and the iterator (at least in terms of behavior and performance).
However, in the essay at the end of this chapter, the author mentioned that in fact, python programmers do not strictly distinguish between the two. Even in the official documents, generators are called iterators, and iterators and generators are synonymous to some extent.
Therefore, if you still feel a little dizzy here, just don't tangle anymore. Just treat the generator and iterator as a pair of twins! Who makes their behavior so similar?
Welcome to leave a message in the comment area to discuss your opinions on these three~
Synchronous update to personal blog system: "Fluent python" learning notes: iteratable objects, iterators and generators