1 Iterator Protocol - Python 描述符协议
2
3 先看几个有关概念,
4 iterator 迭代器,
5 一个实现了无参数的 __next__ 方法, 并返回 '序列'中下一个元素,在没有更多的元素可返回的时候 raises StopIteration 的对象,
6 被称为 iterator(迭代器).
7 在 python 中, 迭代器 'iterator' 同时也实现了 __iter__ 方法, 故 iterators are iterable.
8 经典迭代器 'classic iterators' 从一个集合'collection'中返回元素.
9 生成器 'generator' 也是迭代器, 但可能灵活些, 请参考 generator 一文。
10 例,
11 >>> A = iter('Ads')
12 >>> A
13 <iterator object at 0x00000000036D7320>
14 >>> type(A)
15 <type 'iterator'>
16 >>> dir(A)
17 ['__class__', ... ..., '__iter__', ... ..., 'next']
18 >>> A.next()
19 'A'
20 >>> A.next()
21 'd'
22 >>> A.next()
23 's'
24 >>> A.next()
25 Traceback (most recent call last):
26 File "<input>", line 1, in <module>
27 StopIteration
28
29 iterator
30 Any object that implements the __next__
31 no-argument method which returns the
32 next item in a series, or raises StopItera
33 tion when there are no more items. Python
34 iterators also implement the __iter__
35 method so they are also iterable. Classic
36 iterators, according to the original design
37 pattern, return items from a collection. A
38 generator is also an iterator, but it’s more
39 flexible. See generator
40
41 iterable 可迭代,
42 一个对象,如果该对象可以通过内置方法 'iter' 获得可以个 'iterator',则称该对象是可迭代对象 'iterable'
43 如,
44 >>> A = iter('ABCCcvsds')
45 >>> A
46 <iterator object at 0x00000000036D7320>
47 >>> type(A)
48 <type 'iterator'>
49
50 一个可迭代对象 'iterable object' 可以用于 循环'loops', 列表推导'comprehensions', 元祖拆包'tuple unpacking'.
51 实现了 __iter__ 方法, 返回迭代器'iterator'的对象是可迭代的对象'iterable'. 序列'sequences' 是可迭代对象.
52 实现了 __getitem__ 方法的对象也有可能是可迭代对象.
53
54 iterable
55 Any object from which the iter built-in
56 function can obtain an iterator. An iterable
57 object works as the source of items in for
58 loops, comprehensions and tuple unpack‐
59 ing. Objects implementing an __iter__
60 method returning an iterator are iterable.
61 Sequences are always iterable; other objects
62 implementing a __getitem__ method may
63 also be iterable.
64
65 iterable unpacking 可迭代对象拆包
66 与元祖拆白 'tuple unpacking' 同义. 应用于 'parallel assignment'.
67 例,
68 >>> a = (1,2)
69 >>> b,c = a
70 >>> a
71 (1, 2)
72 >>> b
73 1
74 >>> c
75 2
76 >>> c,b = b,c
77 >>> a
78 (1, 2)
79 >>> b
80 2
81 >>> c
82 1
83
84 parallel assignment
85 Assigning to several variables from items in
86 an iterable, using syntax like a, b = [c,
87 d] — also known as destructuring assign‐
88 ment. This is a common application of tuple
89 unpacking.
90
91 进一步了解一下儿迭代器对象 'Iterator Objects' 和 'Iterator Protocol',
92 Iterator Objects
93 python 中有两种 迭代器对象 'iterator objects'.
94
95 一种是 序列迭代器 'sequence iterator', 用于对'序列对象' __getitem__ 方法的支持.
96
97 另一种是,上例子中常见的迭代器: 一个可调用对象'callable object', 在其上调用 next()
98 方法, 依次放回序列中的元素, 迭代结束的时候返回 StopIteration error(sentinel value).
99
100 迭代器相关源码,
101 与'第一种'迭代器相关,
102 PyTypeObject PySeqIter_Type
103 python 类型对象-'PySeqIter_Type' 为迭代器对象的'类型对象', 由 PySeqIter_New() 函数产生.
104 也是通过 iter(iterable) 内建函数所得到'序列'的类型对象.
105
106 int PySeqIter_Check(op)
107 当 op 是 PySeqIter_Type 类型的时候, 函数返回 true
108
109 PyObject* PySeqIter_New(PyObject *seq)
110 创建一个迭代器对象, 迭代结束后 raises IndexError
111
112 与'另一种'迭代器相关,
113 PyTypeObject PyCallIter_Type
114 由 PyCallIter_New() 创建的可'指定' sentinel value 的迭代器的类型对象. iter(callable, sentinel value)
115
116 int PyCallIter_Check(op)
117 当 op 是 PyCallIter_Type 类型的时候, 函数返回 true
118
119 PyObject* PyCallIter_New(PyObject *callable, PyObject *sentinel)
120 创建一个迭代器对象, 迭代返回 sentinel value 结束, 并 raises IndexError
121 第一个参数是任何 python callable 的对象.
122
123 例子,
124 第一种'迭代器
125 >>> abc = [1,2,3,"S",4,5]
126 >>> a = iter(abc)
127 >>> a
128 <listiterator object at 0x00000000037E0668>
129 >>> a.next()
130 1
131 >> a.next()
132 2
133 >>> a.next()
134 3
135 >>> a.next()
136 'S'
137 >>> a.next()
138 4
139 >>> a.next() # 当迭代器中没有新的数据的时候 StopIteration
140 Traceback (most recent call last):
141 File "<input>", line 1, in <module>
142 StopIteration
143 >>> a # StopIteration 后迭代器对象还存在
144 <listiterator object at 0x00000000037E0668>
145 >>> a.next() # 迭代器返回最后一个数据后,如果想再获取其中的元素, 需要再次生成新的迭代器对象
146 Traceback (most recent call last):
147 File "<input>", line 1, in <module>
148 StopIteration
149
150 另外一种'迭代器
151 >>> b = iter(abc.pop, "S") # abc.pop 是一个 callable 的对象, 指定 StopIteration 的值'S'
152 >>> b
153 <callable-iterator object at 0x00000000037E0668>
154 >>> b.next()
155 4
156 >>> b.next() # next 方法得到元素 'S', raises StopIteration
157 Traceback (most recent call last):
158 File "<input>", line 1, in <module>
159 StopIteration
160
161 Iterator Protocol
162 python 在 C 层面有2个函数跟 迭代器 'iterator' 相关,
163
164 int PyIter_Check(PyObject *o)
165 如果 对象 o 支持 迭代器协议 interator protocol 返回 true.
166
167 PyObject* PyIter_Next(PyObject *o)
168 返回迭代 'iteration' 的下一个元素.
169 o 必须是一个迭代器(*** 注意,该函数本身并不对这一点做验证; 有使用者保证传入的是 iterator),
170 如果没有可以返回的元素, 返回 return NULL (没有exception 描述);
171 如果在获取元素的时候发生了任何的错误 errors, 返回 return NULL 即相应的 exception 描述.
172
173 python 官方示例,
174 PyObject *iterator = PyObject_GetIter(obj);
175 PyObject *item;
176
177 if (iterator == NULL) {
178 /* propagate error */
179 }
180
181 while (item = PyIter_Next(iterator)) {
182 /* do something with item */
183 ...
184 /* release reference when done */
185 Py_DECREF(item);
186 }
187
188 Py_DECREF(iterator);
189
190 if (PyErr_Occurred()) {
191 /* propagate error */
192 }
193 else {
194 /* continue doing useful work */
195 }
iterator 应用的经典示例,
with open('mydata.txt') as fp:
for line in iter(fp.readline, ''):
process_line(line)