Iterator Protocol - Python 描述符协议
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Iterator Protocol - Python 描述符协议相关的知识,希望对你有一定的参考价值。
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)
以上是关于Iterator Protocol - Python 描述符协议的主要内容,如果未能解决你的问题,请参考以下文章