我生活在假设中,定义_ _len _ _和_ _getitem_ _方法对于一个类就足够了,所以它的实例可以通过实例中的for元素迭代,直到它被违反了一个例子.我的原始代码完全不同,但这显示了很好地进入无限循环的问题:
class Limited(object):
def __init__(self, size=5):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, item):
return item*10
if __name__ == "__main__":
test = Limited(4)
assert len(test) == 4
for q in test:
print q
我找不到对终止迭代循环的要求的具体引用,但似乎如果不想遵守完整的Iterator协议,则需要像IndexError或StopIteration这样的异常才能终止.
这是正确的,在哪里找到它记录?
最佳答案 回答
是的,需要IndexError才能终止.
文档
请参阅__getitem__()的文档,其中包含以下注意事项:
Note for loops expect that an IndexError will be raised for illegal
indexes to allow proper detection of the end of the sequence.
基础源代码
创建迭代器的逻辑在Objects / iterobject.c中:
static PyObject *
iter_iternext(PyObject *iterator)
{
seqiterobject *it;
PyObject *seq;
PyObject *result;
assert(PySeqIter_Check(iterator));
it = (seqiterobject *)iterator;
seq = it->it_seq;
if (seq == NULL)
return NULL;
if (it->it_index == PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"iter index too large");
return NULL;
}
result = PySequence_GetItem(seq, it->it_index);
if (result != NULL) {
it->it_index++;
return result;
}
if (PyErr_ExceptionMatches(PyExc_IndexError) ||
PyErr_ExceptionMatches(PyExc_StopIteration))
{
PyErr_Clear();
Py_DECREF(seq);
it->it_seq = NULL;
}
return NULL;
}
算了一些例子
要修复OP的代码,只需要在__getitem __()方法的开头添加两行:
class Limited(object):
def __init__(self, size=5):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, item):
if item >= len(self):
raise IndexError
return item*10
if __name__ == "__main__":
test = Limited(4)
assert len(test) == 4
for q in test:
print(q)
这输出一个有限的序列:
0
10
20
30