python教程—为什么正则匹配对象不能迭代,即使它们实现了_getitem__?-Python实用宝典

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 < em > < / em >地方PyTypeObject __getitem__可以映射到:< a href = " https://docs.python.org/3/c-api/typeobj.html # c.tp_as_sequence”rel = " noreferrer " > tp_as_sequence < / >和< a href = " https://docs.python.org/3/c-api/typeobj.html # c.tp_as_mapping”rel = " noreferrer " > tp_as_mapping < / >。它们都有一个用于_getitem__的slot ([1][2])。

查看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槽(显然_SRE_Match对象为空);如果失败,则如果 PySequence_Check返回true,即一个新的序列迭代器,否则将引发一个类型错误。

PySequenceCheck首先检查对象是dict还是dict子类 -在这种情况下返回false。否则返回值

    s->ob_type->tp_as_sequence && s->ob_type->tp_as_sequence->sq_item != NULL;

由于s- > ob_type- > tp_as_sequence对于_SRE_Match实例为NULL,所以返回0,PyObject_GetIter会引发类型错误:'_sre。对象不可迭代。

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

本文由 Python实用宝典 作者:Python实用宝典 发表,其版权均为 Python实用宝典 所有,文章内容系作者个人观点,不代表 Python实用宝典 对观点赞同或支持。如需转载,请注明文章来源。
1

发表评论