下面是一个简单的模块实现,
spam其中一个函数
myiter(int)返回迭代器:
import spamfor i in spam.myiter(10): print i
打印从0到9的数字。
这比您的情况要简单,但显示了要点:用标准
__iter__()和
next()方法定义对象,以及实现迭代器行为,包括
StopIteration在适当时进行引发。
在您的情况下,迭代器对象需要保留对Sequence的引用(因此,您需要使用deallocator方法将其引用到Py_DECREF)。序列本身需要实现
__iter()__并在其中创建一个迭代器。
包含迭代器状态的结构。(在您的版本而不是m中,它将引用Sequence。)
typedef struct { PyObject_HEAD long int m; long int i;} spam_MyIter;迭代器的
__iter__()方法。它总是简单地返回
self。它允许迭代器和集合在一样的结构中被视为相同
for ... in ...。
PyObject* spam_MyIter_iter(PyObject *self){ Py_INCREF(self); return self;}实现我们的迭代:
next()方法。
PyObject* spam_MyIter_iternext(PyObject *self){ spam_MyIter *p = (spam_MyIter *)self; if (p->i < p->m) { PyObject *tmp = Py_BuildValue("l", p->i); (p->i)++; return tmp; } else { PyErr_SetNone(PyExc_StopIteration); return NULL; }}我们需要
PyTypeObject结构的扩展版本,以便为Python提供有关
__iter__()和的信息
next()。我们希望它们能被有效地调用,因此在字典中没有基于名称的查找。
static PyTypeObject spam_MyIterType = { PyObject_HEAD_INIT(NULL) 0, "spam._MyIter", sizeof(spam_MyIter), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, "Internal myiter iterator object.", 0, 0, 0, 0, spam_MyIter_iter, spam_MyIter_iternext };myiter(int)函数创建迭代器。
static PyObject *spam_myiter(PyObject *self, PyObject *args){ long int m; spam_MyIter *p; if (!PyArg_ParseTuple(args, "l", &m)) return NULL; p = PyObject_New(spam_MyIter, &spam_MyIterType); if (!p) return NULL; if (!PyObject_Init((PyObject *)p, &spam_MyIterType)) { Py_DECREF(p); return NULL; } p->m = m; p->i = 0; return (PyObject *)p;}其余的很无聊…
static PyMethodDef SpamMethods[] = { {"myiter", spam_myiter, METH_VARARGS, "Iterate from i=0 while i<m."}, {NULL, NULL, 0, NULL} };PyMODINIT_FUNCinitspam(void){ PyObject* m; spam_MyIterType.tp_new = PyType_GenericNew; if (PyType_Ready(&spam_MyIterType) < 0) return; m = Py_InitModule("spam", SpamMethods); Py_INCREF(&spam_MyIterType); PyModule_AddObject(m, "_MyIter", (PyObject *)&spam_MyIterType);}


