python - 为什么正则表达式匹配对象即使实现了__getitem__也不能迭代?
问题描述
您可能知道,实现__getitem__
方法使类可迭代:
class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError
return index
demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]
print(hasattr(demo, '__iter__')) # False
但是,这不适用于正则表达式匹配对象:
>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable
值得注意的是,这个异常并没有在__iter__
方法中抛出,因为该方法甚至没有实现:
>>> hasattr(match, '__iter__')
False
那么,如何在__getitem__
不使类可迭代的情况下实现呢?
解决方案
有谎言,该死的谎言,还有 Python 文档。
拥有一个用C__getitem__
实现的类还不足以让它成为可迭代的。那是因为实际上有2个地方可以映射到:和. 两者都有一个用于([1],[2])的插槽。PyTypeObject
__getitem__
tp_as_sequence
tp_as_mapping
__getitem__
查看 , 的来源SRE_Match
,tp_as_sequence
被初始化为,NULL
而tp_as_mapping
被定义。
iter()
内置函数,如果使用一个参数调用,将调用具有PyObject_GetIter
以下代码的 :
f = t->tp_iter;
if (f == NULL) {
if (PySequence_Check(o))
return PySeqIter_New(o);
return type_error("'%.200s' object is not iterable", o);
}
它首先检查tp_iter
插槽(显然NULL
是_SRE_Match
对象);如果失败,则如果 PySequence_Check
返回 true,则生成一个新的序列迭代器,否则TypeError
引发 a。
PySequenceCheck
首先检查对象是 adict
还是dict
子类- 在这种情况下返回 false。否则返回值
s->ob_type->tp_as_sequence &&
s->ob_type->tp_as_sequence->sq_item != NULL;
并且因为s->ob_type->tp_as_sequence
是NULL
例如_SRE_Match
, 0 将被返回,并PyObject_GetIter
raises TypeError: '_sre.SRE_Match' object is not iterable
。
推荐阅读
- python - 如何处理 f2py 模块中的偶尔分段错误
- vba - 将查询从 MS Access 导出到 CSV,带有换行符的冗长文本的列被截断
- java - 将字符串重新复制到新字符串对重新复制数组的性能影响更大吗?
- android - 拥有“发布”apk 后,我应该在 firebase 中删除 SHA1 调试密钥吗?
- java - 类型不匹配无法从可选类型转换
给用户 - linux - 以 ssh 登录时访问客户端计算机目录
- mysql - 如何在 SQL 子查询中使用 NOT IN?
- node.js - 在 nodejs 中创建 workerThread 时,它是否使用运行 nodejs 进程的相同内核?
- java - 你可以为 viewpager2 设置 OnClickListener 吗?
- java - 泛型类型的 Guava ClassToInstanceMap