An iterable object is an object that implements __iter__, which is expected to return an iterator object.
An iterator is an object that implements __next__, which is expected to return the next element of the iterable object that returned it, and raise a StopIteration exception when no more elements are available.
Iterators and iterables can be separate objects, but they don’t have to. Nothing is holding us back here. If you want, you can create a single object that is both an iterator and an iterable. You just need to implement both __iter__ and __next__.
So why did the wise men and women building the language decide to split these concepts? It has to do with keeping state. An iterator needs to maintain information on the position, e.g. the pointer into an internal data object like a list. In other words: it must keep track of which element to return next.
If the iterable itself maintains that state, you can only use it in one loop at a time. Otherwise, the other loop(s) would interfere with the state of the first loop. By returning a new iterator object, with its own state, we don’t have this problem. This comes in handy especially when you’re working with concurrency.
For 循环
Python中的for x in y要求y为iterable,具体地,以下两段代码效果相同:
for x in y: print(x)# <==>it = iter(y)try: a = next(it) print(a)except StopIteration: break
以上遗漏一点:
Python expects iterable objects in several different contexts, the most important being the for statement. In the statement for X in Y, Y must be an iterator or some object for which iter() can create an iterator. These two statements are equivalent:
for i in iter(obj): print(i)for i in obj: print(i)
Note that you can only go forward in an iterator; there’s no way to get the previous element, reset the iterator, or make a copy of it. Iterator objects can optionally provide these additional capabilities, but the iterator protocol only specifies the __next__() method. Functions may therefore consume all of the iterator’s output, and if you need to do something different with the same stream, you’ll have to create a new iterator.
def test2(): lst = [1, -2, 3, -4] ge = (abs(x) for x in lst) lc = [abs(x) for x in lst] print(ge, type(ge)) print(lc, type(lc)) print(next(ge), iter(ge)) print(ge.__next__(), ge.__iter__()) for x in ge: print(x) for x in ge: print(x)>>> <generator object test2.<locals>.<genexpr> at 0x7f5221c61f90> <class 'generator'>>>> [1, 2, 3, 4] <class 'list'>>>> 1 <generator object test2.<locals>.<genexpr> at 0x7f5221c61f90>>>> 2 <generator object test2.<locals>.<genexpr> at 0x7f5221c61f90>>>> 3>>> 4
( expression for expr in sequence1 if condition1 for expr2 in sequence2 if condition2 ... for exprN in sequenceN if conditionN )# <==>for expr1 in sequence1: if not (condition1): continue # Skip this element for expr2 in sequence2: if not (condition2): continue # Skip this element ... for exprN in sequenceN: if not (conditionN): continue # Skip this element # Output the value of the expression.