Iterable object (iterable) [iterable object internally implements the __iter__ method, which returns an iterator object]
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> x
=
[
1
,
2
,
3
]
>>> y
=
iter
(x)
>>> z
=
iter
(x)
>>>
next
(y)
1
>>>
next
(y)
2
>>>
next
(z)
1
>>>
type
(x)
<
class
'list'
>
>>>
type
(y)
<
class
'list_iterator'
>
|
An iterator is an iterable type, for example list_iterator
,set_iterator
for example:
1
2
3
|
x
=
[
1
,
2
,
3
]
for
elem
in
x:
...
|
The real situation is:
Decompiling this code, you can see that the interpreter explicitly calls the GET_ITER
instruction, which is equivalent to calling iter(x)
. The FOR_ITER
instruction is to call the next()
method and continuously get the next element in the iterator, but you can't see it directly from the instruction, because he Optimized by the interpreter.
iterator
An iterator is an object with state, and any object that implements the __iter__ and __next__ (next() in python2) methods is an iterator. __iter__ returns the iterator itself, __next__ returns the next value in the container, or throws an exception if there are no more elements in the container.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
Fib:
def
__init__(
self
):
self
.prev
=
0
self
.curr
=
1
def
__iter__(
self
):
return
self
def
__next__(
self
):
value
=
self
.curr
self
.curr
+
=
self
.prev
self
.prev
=
value
return
value
>>> f
=
Fib()
>>>
list
(islice(f,
0
,
10
))
[
1
,
1
,
2
,
3
,
5
,
8
,
13
,
21
,
34
,
55
]
|
Fib is both an iterable object (implementing the __iter__ method) and an iterator implementation (the __next__ method). The instance variables prev and curr maintain the internal state of the iterator each time the next() method is called. Do two things:
1. Modify the state for the next call to the next() method
2. Generate the return result for the current call
My ultimate example to help you understand iterators
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class
MyIter:
def
__init__(
self
, start
=
0
, end
=
0
):
print
(
'程序的init'
)
self
.start
=
start
self
.end
=
end
def
__iter__(
self
):
print
(
'我在这里制造了一个迭代器'
)
return
self
# 这个地方如果不return self 那么c 就不具备可迭代的能力
def
__next__(
self
):
print
(
'这里调用 __next__方法'
,
self
.start)
if
self
.start <
self
.end:
i
=
self
.start
self
.start
+
=
1
return
i
else
:
raise
StopIteration()
c
=
MyIter(
0
,
5
)
# 代码到这里只是创造了一个迭代器
for
i
in
c:
# 代码到这里 会调用__iter__和__next__ 具有迭代的能力
print
(i)
>>>>>>>>>程序的init
我在这里制造了一个迭代器
这里调用 __next__方法
0
0
这里调用 __next__方法
1
1
这里调用 __next__方法
2
2
这里调用 __next__方法
3
3
这里调用 __next__方法
4
4
这里调用 __next__方法
5
|
generator
A generator is a special kind of iterator, but this kind of iterator is more elegant. The generator does not need to write __iter__ and __next__ methods, but only needs a yield keyword.
A generator must be an iterator (not vice versa)
generator expression
Generator expressions are the generator version of a list comprehension
1
2
3
4
5
|
>>> a
=
(x
*
x
for
x
in
range
(
10
))
>>> a
<generator
object
<genexpr> at
0x401f08
>
>>>
sum
(a)
285
|
Summarize:
* A container is a collection of elements, str, list, set, dict, file, sockets can all be regarded as containers
Containers are iterable
* The iterable object implements the __iter__ method, which returns an iterator object
* The iterator holds an internal state field and the user records the return value of the next iteration. It implements the __iter__ and __next__ methods. The iterator will not load all elements into memory at one time, but will return the result when needed
* Generator is a special kind of iterator, the return value is returned by yield
本文转自http://www.cnblogs.com/mosson/p/8398187.html#_label0