Python 伪序列对象:需要终止异常吗?
我接受这样的假设,即定义Python 伪序列对象:需要终止异常吗?,python,python-2.7,Python,Python 2.7,我接受这样的假设,即定义\uu len\uuu和\uu getitem\uuu方法对于一个类来说已经足够了,因此它的实例可以通过instance:中的for元素进行迭代,直到它违反了一个示例。我的原始代码完全不同,但这很好地说明了问题进入了一个无休止的循环: class Limited(object): def __init__(self, size=5): self.size = size def __len__(self): return s
\uu len\uuu
和\uu getitem\uuu
方法对于一个类来说已经足够了,因此它的实例可以通过instance:中的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
我找不到终止迭代循环的要求的具体参考,但如果不想遵守完整迭代器协议,则终止似乎需要索引器或StopIteration之类的异常
这是正确的吗?在哪里可以找到文件记录?回答
是,需要索引器终止
文档
请参阅带有注释的文档:
注意:对于循环,预期索引器将为非法的
索引以允许正确检测序列的结尾
底层源代码
创建迭代器的逻辑在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__;()方法的开头添加两行:
这将输出一个有限序列:
0
10
20
30
只要实现\uuu getItem\uuu
方法,python就会尝试从0
到infinite
访问所有索引,因此如果不指定何时停止,它将继续调用该方法
只需检查索引值是否高于大小,例如:
class Limited(object):
def __init__(self, size=5):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, item):
if item < self.size:
return item*10
raise IndexError
类别限制(对象):
def uuu init uuuu(自身,大小=5):
self.size=大小
定义(自我):
返回自身大小
定义获取项目(自身,项目):
如果项目<自身尺寸:
退货项目*10
提升索引器
给你一个
class Limited(object):
def __init__(self, size=5):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, item):
if item < self.size:
return item*10
raise IndexError